mirror of
https://github.com/wassname/pi-dynamic-context-pruning.git
synced 2026-06-27 14:00:35 +08:00
chore(release): 1.0.7
- Fix Infinity anchorTimestamp repair on JSON round-trip (blocks extending to end-of-conversation now restored correctly instead of discarded) - Fix nextBlockId calculation to use max(id)+1 instead of array length - Rename internal prompt tag <dcp-message-id> to <dcp-id> - Add regression tests for corrupted-block resilience (PR #3, @wassname) - Update README with Contributors section - Update CHANGELOG for 1.0.7 - Bump package.json to 1.0.7 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
## [1.0.7] - 2026-04-14
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Infinity anchorTimestamp ghost block spiral** — When a `compress` range extended to the end of the conversation, `resolveAnchorTimestamp` returned `Infinity`. `JSON.stringify(Infinity)` serialises to `null`, so on session restore the corrupted block's timestamps coerced to `0` in JS overlap checks, making every new range appear to overlap the ghost block and trapping the model in a compression spiral (101 failures over 2 hours). `resolveAnchorTimestamp` now returns `endTimestamp + 1` instead of `Infinity`.
|
||||
- **Corrupted block propagation on session restore** — `index.ts` now filters out any persisted compression block whose `startTimestamp`, `endTimestamp`, or `anchorTimestamp` is non-finite before restoring state, preventing ghost blocks from surviving across sessions.
|
||||
- **Non-finite timestamp guard** — All code paths that create or apply compression blocks now validate timestamps are finite before proceeding, failing fast rather than silently corrupting state.
|
||||
- **Overlap error diagnostics** — Overlap error messages now include the existing block's timestamp range to aid debugging.
|
||||
- **Prompt tag name mismatch** — The prompt tag was named `<dcp-message-id>` but the code injected `<dcp-id>`; tag name corrected to `<dcp-id>` throughout `prompts.ts`.
|
||||
- **Duplicate test** — Removed a duplicate test case from `pruner.test.ts`.
|
||||
|
||||
### Added
|
||||
|
||||
- **Regression tests** — New test cases for the `Infinity` anchor scenario, `null`-timestamp corrupted blocks, and corrupted-block resilience on session restore.
|
||||
|
||||
Thanks to [@wassname](https://github.com/wassname) for diagnosing and fixing the compression spiral root cause in [#3](https://github.com/complexthings/pi-dynamic-context-pruning/pull/3).
|
||||
|
||||
## [1.0.6] - 2026-04-09
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -148,3 +148,10 @@ npx tsc --noEmit # type-check without emitting
|
||||
```
|
||||
|
||||
The extension is loaded by pi via [jiti](https://github.com/unjs/jiti) so TypeScript is executed directly — no build step required for normal use.
|
||||
|
||||
## Contributors
|
||||
|
||||
[](https://github.com/complexthings) [@complexthings](https://github.com/complexthings)
|
||||
[](https://github.com/wassname) [@wassname](https://github.com/wassname)
|
||||
|
||||
Full contributor list: https://github.com/complexthings/pi-dynamic-context-pruning/graphs/contributors
|
||||
|
||||
@@ -81,17 +81,30 @@ export default function (pi: ExtensionAPI) {
|
||||
const data = entry.data as any
|
||||
|
||||
if (data?.compressionBlocks) {
|
||||
// Filter out blocks with corrupted (null/NaN/Infinity) timestamps —
|
||||
// these were caused by Infinity anchorTimestamp values that became
|
||||
// null after JSON round-trip.
|
||||
const validBlocks = data.compressionBlocks.filter(
|
||||
(b: any) =>
|
||||
Number.isFinite(b.startTimestamp) &&
|
||||
Number.isFinite(b.endTimestamp) &&
|
||||
Number.isFinite(b.anchorTimestamp),
|
||||
)
|
||||
// Filter out blocks with corrupted timestamps, then repair
|
||||
// anchorTimestamp which is legitimately Infinity for blocks that
|
||||
// extend to end-of-conversation (JSON round-trips Infinity as null).
|
||||
const validBlocks = data.compressionBlocks
|
||||
.filter(
|
||||
(b: any) =>
|
||||
Number.isFinite(b.startTimestamp) &&
|
||||
Number.isFinite(b.endTimestamp),
|
||||
)
|
||||
.map((b: any) => ({
|
||||
...b,
|
||||
// anchorTimestamp is Infinity when the block extends to the end
|
||||
// of the conversation; JSON round-trips Infinity as null, so
|
||||
// repair it here rather than discarding the block.
|
||||
anchorTimestamp: Number.isFinite(b.anchorTimestamp)
|
||||
? b.anchorTimestamp
|
||||
: Infinity,
|
||||
}))
|
||||
state.compressionBlocks = validBlocks
|
||||
state.nextBlockId = data.nextBlockId ?? state.compressionBlocks.length
|
||||
state.nextBlockId =
|
||||
data.nextBlockId ??
|
||||
(state.compressionBlocks.length > 0
|
||||
? Math.max(0, ...state.compressionBlocks.map((b: any) => b.id)) + 1
|
||||
: 1)
|
||||
state.tokensSaved = data.tokensSaved ?? 0
|
||||
state.totalPruneCount = data.totalPruneCount ?? 0
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@complexthings/pi-dynamic-context-pruning",
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.7",
|
||||
"description": "PI coding agent extension — Dynamic Context Pruning (DCP)",
|
||||
"keywords": [
|
||||
"pi-package",
|
||||
|
||||
Reference in New Issue
Block a user