mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 18:55:22 +00:00
32 KiB
32 KiB
Changelog
Keep-a-Changelog style (## [X.Y.Z] - <date>, newest first), matching sibling
pi packages (e.g. pi-cohort).
Upstream releases are published to npm as pi-condense. This repository maintains the source directly inside the my-pi bundle; see UPSTREAM.md.
[my-pi-unreleased]
- Imported official
v2.9.1source at commit59c95110aacd8131db71e21296765dd80b72fae8and replaced the root npm dependency withfile:./pi-condense. - Integrated the former bundle-injected defaults directly into
DEFAULT_CONFIG: enabled pruning,agent-message/turn, 73.5% total-budget and 4% turn-delta triggers, default model/thinking, 90s idle and 300s attempt ceilings, and non-quiet oversized skips. Missing settings now use these values in memory without rewriting explicit user configuration. - Added transient summarizer retries with configurable retry count, base delay, and maximum delay. Maintained defaults make up to three total attempts (
summarizerMaxRetries: 2) with1s → 2sbounded exponential backoff; a distinct session-model fallback consumes the final retry slot, abort remains prompt, and the final error is emitted only after exhaustion. - Added settings UI/status visibility, normalization, documentation, and tests for the maintained defaults and retry lifecycle.
[2.9.1] - 2026-08-18
- Orphan sweep: any foreign message is now a barrier (#11).
sweepOrphanToolResultsonly reset its open-call set onassistantmessages, while pi-ai flushes synthetic tool results at bothassistantanduserboundaries (convertToLlmmapscustom/branchSummary/compactionSummary/bashExecutiontouser). A foreign message spliced between a toolCall and its toolResult (observed: a pi-cohort control notice) let the real result through alongside pi-ai's synthetic - a duplicatetool_use_idthe provider rejects permanently (Anthropic 400, branch bricked). Now any message that is neitherassistantnortoolResultclears the open set, so the interleaved result is swept and pi-ai's repairable synthetic stands alone; already-broken branches un-brick on the next render. Deliberate conservative over-sweep (unknown roles,excludeFromContextbashExecution) - no role allowlist. Test helperexpectNoOrphanToolResultscarries the identical rule. Spec:doc/specs/2026-08-18-gh-11-orphan-sweep-barrier.md(partially supersedes the 2026-08-12 spec's section C).
[2.9.0] - 2026-08-14
- Uncovered chains now compress deterministically instead of stranding forever (#10). Chain compression (Phase 3) required per-batch summary coverage; a closed eligible chain whose span produced no summaries (trivial batches,
skipped-oversized, fully-deduped spans, capture misses) hit a permanentno-summaryskip - once the prune frontier passed it, nothing could ever reclaim it. The motivating incident left a 639-call, ~935k-char chain (~62% of a 620k window) live in context indefinitely.- Deterministic zero-LLM fallback. When coverage is zero,
compressEligibleextracts the chain's middle tool calls positionally (resolveRange; protected and already-indexed members excluded), backfills them into the tool-call index, and compresses the chain with a synthetic body - call count, tool histogram, span duration, first/last args excerpts (200-char cap), andt<N>refs - carried inrangeSummaryTextwith a new optionalbodySource: "deterministic"marker. No summarizer traffic, no renderer changes, body render-stable (cache-friendly after the one-time compression). - Mandatory fail-closed recoverability backfill. New
ToolCallIndexer.backfillChainRecords: append-before-commit atomicity (in-memory maps mutate only after thecontext-prune-indexentry persisted), oversized results spilled via the sharedapplySpillhelper (extracted from the eager spill path), refs ride the backfilled entry (backfilled: true+refs) so they survive restart without a summary message, and backfilled records never seed content-hash dedup canonicals - live or on reconstruction. Any failure preserves the historical skip; the next flush retries and converges by composing from durable records without duplicate index entries. - Edge cases. Fully-protected chains keep the plain skip (compressing would save zero tokens - every output relocates verbatim). A genuine span mismatch (zero extractable, zero indexed, not fully protected) emits a new
backfill-emptydiagnostic (widget segment is nowdiag u/m/o/b)./pruner compacthandles all uncovered chains in one pass. Known limitation: an idle session heals a stranded chain on the next working flush or/pruner compact, not via/pruner nowon an empty queue. - Anti-regression cage. Covered-path entries pinned byte-identical; legacy chain/index entries round-trip unchanged; restart-mid-failure-window convergence, fully-deduped backfill, protected exclusion+verbatim relocation, and multi-chain compact all integration-pinned. All optional fields - pre-upgrade sessions load with today's semantics.
- Docs.
PRUNING.mddeterministic-fallback subsection + diagnostics row, README widget legend + compact note, AGENTS.md entry-table updates. Spec:doc/specs/2026-08-14-uncovered-chain-deterministic-backfill.md.
- Deterministic zero-LLM fallback. When coverage is zero,
[2.8.0] - 2026-08-13
- Both token-budget flush triggers now cap the context window they reason about at 300,000 tokens (
MAX_BUDGET_WINDOW,src/budget.ts) (#7). Previously both scaled purely off the model's advertised window, which made them unreachable as windows grew: on a 1M-window modelautoBudgetThreshold: 0.9meant 900k tokens - a session ends long before that, so pruning never fired - while the same setting worked on a 200k model.budgetTurnDelta: 0.1was worse than late: it meant +100k context growth inside a single turn, which effectively never happens, so the re-arm trigger was dead.autoBudgetThresholdnow fires atmin(300_000, threshold * contextWindow)tokens - your percentage of the model's window, or 300k tokens, whichever comes first. The threshold keeps its literal meaning; the cap is only a ceiling.budgetTurnDeltaapplies the same ceiling in the other shape - a 300k ceiling on a single turn's growth could never bind - so the fraction is measured againstmin(contextWindow, 300_000):0.1means +30k tokens in one turn on any model at or above 300k (+20k on a 200k model, unchanged).- No new setting, and no behavior change for any model advertising 300k or less, at any setting - a 256k window at
0.9still fires at 230.4k. Above 300k flushes happen earlier; nothing ever flushes later than before. Downward control is unaffected:0.1on a 1M model still means 100k tokens. usageFractionmay now exceed1.0above the ceiling (600k tokens on a 1M window returns2.0) and is deliberately not clamped - clamping would saturate the delta trigger and stop it re-arming.- Docs updated in step:
README.md,doc/configuration.md,PRUNING.md. Spec:doc/specs/2026-08-13-budget-window-cap.md.
[2.7.0] - 2026-08-12
- Single-chain observability + reload trigger repair (#6). A 5-hour, 256-turn session running one uninterrupted tool chain (no text-only assistant reply ever closed it) accumulated ~195k tokens of raw toolResults while
/pruner statusshowed near-zero activity: chain compression (Phase 3) requires closed chains by design, and a session reload cleared the in-memory pending queue, leaving the automatic flush trigger stranded even though the branch rescan could recover the work.- Reload rearm.
session_start/session_treenow probe the branch via the existing capture rescan (no LLM work); when completed unsummarized batches exist past the frontier, a transientrearmedPendingflag makes theturn_endbudget/delta gate reachable without a freshly pushed batch - the next threshold crossing flushes automatically. Boolean only: no queue reconstruction, no flush at boot; reload followed by total idleness gets visibility, not silent compaction. Probe failures are reported (console.error) and never fail the reload. With the flag unset,turn_endbehavior is byte-identical to before (regression-pinned). - Context metrics. New pure module
src/context-metrics.tscomputes what the pruner cannot (yet) reclaim: open-cycle thinking tokens (thinking blocks in the trailing open segment), largest-chain share (max of largest closed chain vs the open segment, % of total branch chars), and frontier gap (summarization-eligible unsummarized toolResults past the frontier, occurrence-keyed and protection-aware). Allchars/4estimates over the persisted branch, including persisted summary messages. - Surfacing.
/pruner statusgrows a--- context ---block (plusrearmed: yeswhen armed); the footer status line grows a self-hiding· think Nk · gap Nk · chain P%suffix (rendered only while the frontier gap is non-zero);agent_endshowsprune: recovered pending (reload)instead of a misleading0 pending. - New
context-prune-flush-metricssession entry. One per flush attempt - every outcome includingemptyanderror, singlefinallyemit site, delivery-routed writer - recording the trigger (budget/delta/message-end/manual/rearmed), batch counts, and the pre-flush metrics snapshot. Append-only observability log: never in LLM context, never reconstructed on load; exists so the next incident of this shape is diagnosable post-hoc.cost:externalpayload andSummarizerStatssemantics unchanged. - Docs.
PRUNING.mddocuments the single-chain limitation (a design property of Phase 3) withautoBudgetThreshold/budgetTurnDeltaguidance for long autonomous runs; README,doc/configuration.md, and the AGENTS.md entry table cover the new surfaces. Spec:doc/specs/2026-08-12-single-chain-observability-trigger-repair.md. - Also hardens the test suite's
@earendil-works/pi-ai/compatmocks to preserve real module exports (they were silently layout-sensitive under flat/deduped node_modules installs).
- Reload rearm.
[2.6.0] - 2026-08-12
- Fix: reused provider tool-call ids could delete a live turn and produce a rejected request (#8). Provider
toolCallIds (e.g.bash_23) are unique only within one response - some providers restart a${tool}_${n}counter, so the same bare id recurs across a session denoting different tool calls.applyChainCompressionstreated the id as session-durable identity: it unioned every persisted chain entry'sdroppedToolCallIdsinto one session-wide set and dropped any message matching it anywhere in the array, deleting a live assistant turn that happened to reuse a compressed chain's id and orphaning its tool result - rejected outright by Anthropic (unexpected tool_use_id found in tool_result blocks) and Kimi K3 (unresolvable tool name), unrecoverable without hand-editing the session JSONL. The same bare ids also mis-keyed the indexer, dedup,isSummarized, and batch capture.- Positional chain ranges.
applyChainCompressionsnow resolves each persistedChainCompressionEntryto an index range viaresolveRange(src/chain-range-prune.ts): exactly oneuser-role message atstartUserTimestamp, exactly oneassistant-role message atfinalAssistantTimestamp,start < end- any other outcome (includingfinalAssistantTimestamp === null) drops nothing and inserts no synthetic, fail-closed. Drops are role-restricted toassistant/toolResult/ per-batch-summary messages inside the range, souser-role messages - including the user-role<compressed-chain>synthetic, which keeps re-application idempotent - and third-partycustom_messageentries survive. Per-batch summary suppression stays coverage-based (toolCallRefsoverlap), not index-membership, because underbatchingMode: "agent-message"the summary lands after the range.droppedToolCallIdsis retained only as a diagnostic cross-check against the range's actual contents; the range always wins. - Occurrence-keyed identity. Records are now keyed
id@resultTimestamp(src/occurrence-key.ts), the discriminant being theToolResultMessage's own timestamp (notToolCallRecord.timestamp, which is a batch-level timestamp computed inconsistently between the live-capture and session-rescan paths). Persisted shapes gained optionalresultTimestamp(index records, summary refs),newResultTimestamp/originalResultTimestamp(dedup aliases), anddroppedOccurrenceKeys(chain entries) - all optional, so pre-upgrade entries keep bare-id keying and a session spanning the upgrade retains today's behavior for its pre-upgrade half.isSummarizedis now a strict occurrence-key lookup; the sole sanctioned bare-id fallback ishasLegacyBareRecord, true only for a bare id with no occurrence-keyed siblings (a mixed id fails closed on both). Spill sidecars are named from the occurrence key going forward; recovery still reads the persistedspillPath, so pre-upgrade blobs keep resolving. - Orphan sweep.
pruneMessagesnow ends with a structural post-condition,sweepOrphanToolResults(src/orphan-sweep.ts): one forward pass with per-turn open-call tracking (each assistant message replaces the open set rather than accumulating into it, so an id used validly early cannot license a later genuine orphan under the same reused id) removes anytoolResultno surviving assistant opened. Provider-agnostic and structural rather than keyed to any provider's error string; reference-preserving when nothing is swept, so the no-op / prompt-cache-prefix invariant (doc/specs/2026-08-04-pruner-noop-serialization.md) holds. - Diagnostics. New
context-prune-diagnosticsession entry ({ kind, detail }, kindsunresolved-range/range-id-mismatch/orphan-sweep) surfaces these degradations without ever entering LLM context - zero tokens, zero cache-prefix change. Deduped per(kind, dedupKey), reset onsession_start/session_tree. The/prunerstatus line grows a self-hiding· diag u<N>/m<N>/o<N>segment (u/m/o map to the three kinds above in that order); each zero counter is omitted and the whole segment disappears when all three are zero. context_tree_querymulti-occurrence recovery. A raw provider id that was reused now returns every matching occurrence (not just one), each labelledid@timestamp, chronologically; a legacy record with noresultTimestampis labelled with the bare id plus an explicitOccurrence: legacy (no resultTimestamp)line. Short refs (tN) are unaffected - still 1:1 and the primary recovery path.- Accepted limitation: a session that spans the upgrade keeps bare-id keying for everything captured before it landed; only the post-upgrade half of such a session gets occurrence-keyed identity. No migration runs on load. Concretely, within such a session a live tool result whose provider id collides with a pre-upgrade summarized record can still be stub-replaced with that record's stale content (
hasLegacyBareRecord's bare-id fallback insrc/pruner.tscannot distinguish the two once both denote the same bare id with no occurrence-keyed siblings); new records are unaffected, and the exposure disappears once a session contains no legacy records.
- Positional chain ranges.
[2.5.0] - 2026-08-05
- Removed the main-loop thinking strip (breaking:
contextPrune.thinkingStrip.*no longer read). The feature assumed thinking blocks we send are thinking blocks we are billed for. Verified against the live Anthropic API (count_tokensand real billed usage agree to the token), the actual rule is: thinking in a closed cycle bills 0 input tokens, and thinking in an open cycle survives only as an unbroken run starting at the cycle's first assistant turn — any gap discards everything after it.keepLastTurnskept the last K, so firing it punched a gap at the front and the API dropped all of it: the model received no thinking either way, and the no-gap → gap transition cost a full cache invalidation (measured +33% in a controlled 24-tool-call A/B, $0.6430 → $0.8531, with turn 17 rewriting 63113 tokens at 0% reuse). Across 58 sessions / 1233 open cycles the strip fired 253 times and reached its ~130-turn break-even twice. It was also redundant: chain compression's synthetic block is arole: "user"text message, which closes the cycle and frees all prior thinking server-side at zero cache cost.pruneMessagesdrops to three phases (stub-replace → error-purge → chain-range-prune);src/thinking-strip.ts,ThinkingStripConfig,KEEP_LAST_TURNS_PRESETS, the two/prunersettings entries, andPruneFrontier.thinkingStripBoundaryTimestampare gone. A leftoverthinkingStripblock insettings.jsonis inert and round-trips untouched (normalize()never filters unknown keys); a persistedcontext-prune-frontierentry carrying the old boundary field loads and is ignored. Rationale and measurements:doc/specs/2026-08-05-remove-thinking-strip.md.
[2.4.3] - 2026-08-04
- Flush-gated, timestamp-keyed thinking strip (#3). Phase 4 (
stripOldThinking,src/thinking-strip.ts) recomputed its keep-window from the live assistant count on everycontextrender, so each turn the(count - keepLastTurns)-th assistant slid forward and its thinking was stripped deep in history. pi-ai sets prompt-cache breakpoints only attools + system + last message(verified in@earendil-works/pi-aiapi/anthropic-messages.jsconvertMessages- no in-history breakpoint), so every deep mutation busted the cached suffix - roughly every render inside a tool loop. The strip boundary is now a flush-computed, persisted assistant-message timestamp (thinkingStripBoundaryTimestamp, added to thePruneFrontiersnapshot on the existingcontext-prune-frontierentry): fixed between flushes so consecutive renders are byte-stable in their historical prefix (the cache survives a whole tool loop), advancing only on a non-empty flush (piggybacking summarization's own cache bust - zero marginal busts), monotonically clamped (never re-adds thinking to an already-stripped message, even whenkeepLastTurnsis increased mid-session), and keyed by timestamp rather than array index so it is robust to phase-3 chain-range middle drops. An absent boundary (pre-feature sessions, pre-first-flush) falls back to the original live-count window verbatim. Additive optional field, fully backward-compatible; no new config key,keepLastTurnspresets unchanged.PRUNING.mdcache-impact model corrected. Turns the old k-busts-per-render into ~1-per-request.
[2.4.2] - 2026-08-04
- No-op renders skip context serialization.
pruneMessages(src/pruner.ts) computedsizeMessages(a fullJSON.stringifyover the entire message array) unconditionally on everycontextrender, including no-ops where the result is never read (index.tsconsumesbeforeChars/afterCharsonly underif (result.pruned)). It now computes both sizes lazily in the pruned branch and returns a{ beforeChars: 0, afterChars: 0 }sentinel on a no-op, so a render that prunes nothing does zeroJSON.stringifyover the array. CPU/GC only - zero token cost, no wire or return-shape change. Also corrects a stale fast-path comment in thecontexthandler (index.ts): index/registry emptiness alone does not imply a no-op, because error-purge and thinking-strip prune independently. - Bumped
engines.nodeto>=22.19.0to match the host pi runtime (@earendil-works/pi-coding-agent@0.83.0); drops advertised support for Node 20/21, which cannot run current pi. Bumped the@sinclair/typeboxdevDependency floor to^0.34.52(freshness only; the caret already resolved there).
[2.4.1] - 2026-07-30
- Fix 421 Misdirected Request for GitHub Copilot business/enterprise seats. The summarizer called pi-ai's
stream()with the static model definition, whose shippedbaseUrlpins the individual Copilot host (api.individual.githubcopilot.com); business/enterprise tokens are rejected there with421 Misdirected Request, so anygithub-copilot/*summarizerModelfailed on those seats.runOncenow mirrors the main agent loop (pi'smodel-runtime): it resolves provider auth viactx.modelRegistry.getProviderAuth(model.provider)and, when the resolved auth carries a seat-specificbaseUrl, rebases the model onto it before streaming. Also bumps@earendil-works/*devDependencies to^0.83.0(needed forgetProviderAuthon the extension-facingModelRegistry) and importsstreamfrom@earendil-works/pi-ai/compat(its export moved off the root in current pi-ai).
[2.4.0] - 2026-07-09
- Summarizer call timeout. Every summarizer stream call is now bounded by an idle timeout (
summarizerIdleTimeoutMs, default 20s - reset on every stream event, so it never false-aborts a flowing or reasoning generation) and a total-duration ceiling (summarizerMaxTimeoutMs, default 180s). Previously a stalled-but-open provider connection hung the whole agent turn indefinitely, sincerunOncehad no time budget and the automatic flush paths pass no abort signal. A timeout classifies as transient and feeds the existing outage-fallback retry (one bounded session-model attempt when a distinctsummarizerModelis set), then surfaces awarningnotice. Both timers are0-disablable and exposed in/pruner settingsand/pruner status.
[2.3.0] - 2026-07-06
- Recovery grace window for
context_tree_queryoutput. The pruner used to re-stub its own recovery output at the next turn boundary, forcing a retrieve -> re-stub -> re-query loop the agent experiences as "fighting the pruner" (observed in a real session: a recovered tool dump was re-summarized on the very next flush, so the agent had to keep re-querying the same ref). A newrecoveryGraceTurnssetting (default3,0disables) keeps a recovered output verbatim for that many user-turn-groups before reverting to the stub. Enforced at render time in two places - Phase 1 stub-replace (src/pruner.ts) and chain-compression eligibility (src/chain-compressor.ts, which defers compressing any chain whose span still holds an in-grace recovery id) - never at capture, so the frontier, dedup, spill, and liveturn_endpaths are unchanged. The window is computed positionally from the message stream (no newToolCallRecordfield). Default3covers ~81% of same-ref re-queries observed in the local session corpus; the accepted trade-off is that a reference past the window is re-stubbed and may be re-queried, keeping context regrowth bounded rather than permanent. Tunable via/pruner recovery-grace [n]and the/pruner settingsoverlay. See PRUNING.md § What Pruning Does.
[2.2.1] - 2026-07-06
- Fix probe starvation in the summarizer outage fallback.
FallbackController.onFallbackOnlyFailreset the re-probe cooldown on every steady-state fallback failure, so a fallback (session) model that failed at least once per 10-minute cooldown perpetually pushed out the primary re-probe - a recoveredsummarizerModelwas never re-tested and summarization stayed on the pricier session model indefinitely (the exact stall the feature exists to kill, in the fallback direction). The method is now a no-op onlastProbeAt: the primary re-probe fires on schedule regardless of fallback failures. In-memory only; no wire/config change.
[2.2.0] - 2026-07-06
- Summarizer outage fallback to the session model. Per-model provider outages (e.g. a cheap
summarizerModellike Haiku degraded while the session's main model stays healthy) previously stalled pruning for the whole outage -runSummarizationreturned null and the batch retried the same dead model every flush, growing context unbounded. A new sticky in-memoryFallbackController(src/summarizer-fallback.ts) now routes summarization toctx.modelon a transient failure of the configured model, retrying the failed call once on the session model. Fallback is sticky: while engaged, all calls use the session model until a single probe batch re-tests the configured model after a 10-minute cooldown, then auto-recovers. Trigger is transient-only - auth (pre-flight key failure), unusable (empty/truncated), and abort never trip it. A one-timewarningfires on enter and aninfoon recovery viactx.ui.notify(UI only, never injected into LLM context). No config key: the target is alwaysctx.model, and the controller is inert when no distinct fallback model exists (summarizerModel: defaultor the resolved model equalsctx.model), preserving today's single-attempt behavior byte-for-byte. State is in-memory only (reset onsession_start, nocontext-prune-*entry).
[2.1.2] - 2026-07-05
Branding, funding, and gallery preview. No behavior change.
Added
- Logo + pi.dev gallery preview. Repo-root
pi-condense.png(640x640), shown in the README and wired aspi.image. - Buy Me a Coffee funding.
fundinginpackage.json,.github/FUNDING.yml, and a README badge.
Changed
- Sharpened
description; addedcontext-pruning,llm,prompt-cachingkeywords. - README reframed product-first (credit to
championswimmer/pi-context-prunekept as attribution); fixed a stalepi-superpowers->pi-gauntletreference in a spec doc.
[2.1.1] - 2026-07-04
release.ymlposts GitHub Release notes. A newrelease-notesjob (needs: publish,contents: write) extracts the CHANGELOG section matching the pushed tag withawk(skipping## [Unreleased]) and publishes it as the GitHub Release body viagh release create(falling back togh release edit). No LLM or API key; onlygithub.token.
[2.1.0] - 2026-07-04
- Per-bullet recovery refs in prune summaries (closes #2). Each per-tool block in a summary now carries its own inline
`tN`ref, so the model recovers a specific tool's raw output in one hop instead of guessing which flat-footer ref maps to which bullet. The serializer labels each tool block[[N:toolname]](src/batch-capture.ts), the summarizer prompt tells the model to copy that label onto its first bullet (src/summarizer.ts), andsubstituteInlineRefs(src/summary-refs.ts) validates the echoed tool name against the tool at position N before rewriting to`tN`. The flat footer is retained unchanged as the always-correct fallback. Deterministic number->shortId map over the shared post-dedupbatch.toolCallsorder; the tool-name tag downgrades a confident wrong-ref (skip-induced renumber) to footer-only, and mismatched / out-of-range / wrapped / mid-line labels are stripped (fence-aware leak guard) so no raw[[N:name]]token ever leaks into context. No new tool, config key, or index.
[2.0.1] - 2026-07-03
- Prune summaries are now hidden from Pi's main window (
display: falseat both injection sites inindex.ts). They stay in LLM context and session history (recoverable viacontext_tree_query) but no longer print the full markdown block into the TUI. Mirrors upstreampi-context-prune2fd6127. - Sharpened the summarizer prompt (
src/summarizer.ts): the key-outcome bullet now requires copying file paths, identifiers, signatures, and error strings verbatim (never reworded), and the summarizer skips tool calls that succeeded with nothing reusable to record. Scoped to short tokens - values/full output stay summarized, so the ~8x median compression and the oversized guard are unaffected. context_tree_querydescription now shows a literal call example ({ toolCallIds: ["t12", "t3"] }) and consolidates the two near-duplicate parameter descriptions into one that marks the field required. Reduces the empty-first-call retry seen in real sessions. No schema or behavior change.
[2.0.0] - 2026-07-02
- Renamed the package
pi-context-prune->pi-condenseand switched distribution from git-tag pins to npm. Install withpi install npm:pi-condense(wasgit:github.com/jjuraszek/pi-context-prune@vX.Y.Z). Migrate pinnedsettings.jsonentries;release.sh sync-presetsreports stale pins. - Added npm release machinery:
.github/workflows/release.yml(tag-triggered, OIDC + provenance,tag == package.jsongate) andtest.yml(bun, Ubuntu + Windows matrix). Portedrelease.shto the shared sibling skeleton (propose/patch|minor|major/current/verify/sync-presets), replacing the old tag-pinrelease.mjs. - Added
LICENSE(MIT),filesallowlist,engines, andauthortopackage.json; removed deadpi.skills/pi.promptsmanifest entries (those directories never existed). - Renamed the cost-event producer id
EXTERNAL_COST_SOURCE"pi-context-prune"->"pi-condense". Aggregators keyed on the oldsourcestring see it as a new producer.
[1.0.0] - 2026-05-31
- Removed three
pruneOnmodes, leavingagent-message(default) andon-demand:every-turn- debugging-only trigger with the worst prompt-cache churn.on-context-tag- depended on the externalttttmr/pi-contextextension and overlapped itscontext_compact.agentic-auto- the scaffolded DCP-style model-drivencontext_prunetool was never wired to range compression (seePRUNING.md, Future Work).
- Removed the
context_prunetool, the agentic-auto system prompt, the<pruner-note>unpruned-count reminder, and theremindUnprunedCountsetting. Deletedsrc/reminder.ts,src/context-prune-tool.ts,src/progress-text.ts. - Migration: none required. Configs pinned to a removed mode fall back to
agent-messageviaisPruneOn(). A staleremindUnprunedCountkey insettings.jsonis ignored.
[0.11.1] - 2026-05-28
- Release flow:
release.shnow rewrites every~/.pi/agent*/settings.jsonpin ofgit:github.com/jjuraszek/pi-context-prune@<ref>to the new@vX.Y.Zautomatically after pushing the tag. Opt out with--no-update-pins. Aligns this fork's release workflow with sibling pi-* packages. - Docs:
README.mdinstall section leads with the jjuraszek tag-pin (was upstream npm/sha references).AGENTS.mdrelease blurb updated to reflect tag pins + automatic settings rewrite..agents/skills/release/SKILL.mddocuments the new flow + flags. Adds thisCHANGELOG.mdfor parity with sibling pi-* packages.
[0.11.0] - 2026-05-28
- Pre-flush pipeline: content-hash dedup (re-reads of identical
(toolName, content)pairs alias the original instead of going through the LLM), trivial-batch skip (minBatchChars), protected tools allowlist, stub-replace rather than delete. SeePRUNING.md, Pre-flush Pipeline & Safeguards. - Settings: moved to
<agent-dir>/settings.json#contextPrunenamespace (was a separate file). Honors$PI_CODING_AGENT_DIR.
[0.10.0] - 2026-05-11
quietOversizedSkipssetting to suppressskipped-oversizednotifications.- Demote oversized-skip notification severity to info.
- Use short refs in pruned summaries (e.g.
t1,t2rather than full toolCallIds) so the model can pass them back throughcontext_tree_querymore reliably.
[0.9.x] - 2026-05-05 to 2026-05-11
0.9.3: spinner animation fix for/pruner now.0.9.2: replace footer progress with aboveEditor widget during/pruner now.0.9.1: allowESCto cancelcontext_prunetool call.0.9.0: agentic-auto mode (pruneOn: "agentic-auto"),context_prunetool surfaced to the LLM,remindUnprunedCountsetting.
[0.8.x] - 2026-05-04 to 2026-05-05
0.8.1: bug fixes around session-start index rebuild.0.8.0:agent-messagetrigger mode + batching, footer status widget.
[0.7.0] - 2026-05-04
on-context-tagtrigger mode (integrates withpi-contextcontext_checkpoint).
[0.6.x] - 2026-05-02
- Tree browser (
/pruner tree) + summary overlay (Ctrl-O). dedupByContentHashcross-flush dedup.
[0.5.0] - 2026-05-01
- Cumulative summarizer token/cost stats (
/pruner stats).
[0.4.0] - 2026-05-01
- Configurable summarizer model + thinking level (
/pruner model,/pruner thinking).
Earlier (v0.1.x - v0.3.x)
Initial extension scaffolding, context_tree_query tool, base summarization loop, session-JSONL index persistence. See git log for granular history.