pi-smart-compact 10.1.3 → 10.1.5

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 CHANGED
@@ -2,6 +2,53 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [10.1.5] - 2026-10-05
6
+
7
+ ### Release approval
8
+
9
+ - Patch release approved by the release owner after the deterministic gates
10
+ on the exact candidate. No version-specific applied-canary cohort or live
11
+ provider run exists for `10.1.5`; the fix is evidenced by unit tests and
12
+ offline replay of a recorded session's cache usage only.
13
+
14
+ ### Fixed
15
+
16
+ - **Anchor prompt cache no longer evicts the rolling cache marker on OAuth
17
+ payloads.** pi-ai places `cache_control` on both OAuth system blocks (the
18
+ Claude Code identity line and the system prompt), so an Anthropic request
19
+ already carries four breakpoints: identity, system prompt, tools, rolling
20
+ tail. Adding the anchor marker made five, and the limit enforcement dropped
21
+ the first foreign message marker, which was the rolling tail. From the
22
+ first turn after an anchor every request then read only the prefix up to
23
+ the anchor and wrote nothing: `cacheWrite` stayed 0 while uncached input
24
+ grew turn by turn (a recorded session fell from 99% to 40% cache hits and
25
+ stayed there through a compaction that kept the anchor). The rolling tail
26
+ is now never an eviction candidate; the redundant identity marker goes
27
+ first, then the tools marker, both of which only cover prefixes of the
28
+ system-prompt marker. API-key payloads (one system marker) were unaffected.
29
+
30
+ ## [10.1.4] - 2026-10-02
31
+
32
+ ### Release approval
33
+
34
+ - Patch release approved by the release owner after the deterministic gates
35
+ on the exact candidate. No version-specific applied-canary cohort or live
36
+ provider run exists for `10.1.4`; the fix is evidenced by unit tests and
37
+ offline replay of recorded sessions only.
38
+
39
+ ### Fixed
40
+
41
+ - **Evidence lines no longer manufacture a file by cutting through a path.**
42
+ `summaryEvidenceLine` cut at the character limit wherever it fell; the
43
+ cross-compaction delta cuts loop summaries at 60 characters, and in a
44
+ recorded session that landed inside `.json`, so the summary carried
45
+ `OPENCLAW_HOME/.openclaw/openclaw.js`, a file that never existed. The
46
+ verifier flagged it as fabricated (repairable, so not blocking), but a
47
+ reader of the summary would have looked for it. The cut now backs off to
48
+ the last separator inside the split token (a true directory prefix) or to
49
+ the token start; shorter cuts remain prefixes of longer renderings, so
50
+ needle checks keep matching.
51
+
5
52
  ## [10.1.3] - 2026-10-02
6
53
 
7
54
  ### Release approval
@@ -16,7 +16,9 @@
16
16
  * reply after N yet) N's prefix has never been written. The previous anchor M
17
17
  * keeps a marker too, [system, tools, M, N], so the prefix through M is read
18
18
  * and only (M, N] is written. The bridge uses a free slot or displaces a
19
- * foreign message marker; it never evicts system/tools markers.
19
+ * redundant foreign marker (see `evictable`); it never displaces the rolling
20
+ * tail, which is what advances the cache every turn (pi-ai's OAuth layout
21
+ * already carries four markers: identity, system prompt, tools, tail).
20
22
  *
21
23
  * TTL follows the payload: a `1h` marker (Pi long retention) makes the anchor
22
24
  * `1h` and rolling markers after it `5m`; otherwise markers stay default.
@@ -1 +1 @@
1
- {"version":3,"file":"anchor-cache.d.ts","sourceRoot":"","sources":["../../src/app/anchor-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,KAAK,iBAAiB,GAAG,IAAI,CAAC,aAAa,EAAE,0BAA0B,GAAG,2BAA2B,CAAC,CAAC;AA6CvG,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAC5B,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;CAAE,GACxC,IAAI,CAEN"}
1
+ {"version":3,"file":"anchor-cache.d.ts","sourceRoot":"","sources":["../../src/app/anchor-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,KAAK,iBAAiB,GAAG,IAAI,CAAC,aAAa,EAAE,0BAA0B,GAAG,2BAA2B,CAAC,CAAC;AA6CvG,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAC5B,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;CAAE,GACxC,IAAI,CAEN"}
@@ -8,7 +8,7 @@ import type { CompressionProfile, ProfileConfig } from "./types.ts";
8
8
  * `package.json#version`. Do not hand-edit this line for releases; bump
9
9
  * package.json and run `bun run sync-version`.
10
10
  */
11
- export declare const VERSION = "10.1.3";
11
+ export declare const VERSION = "10.1.5";
12
12
  /**
13
13
  * Opt-in components that are not installed with the extension: optional peer
14
14
  * dependencies in package.json, pinned to the versions the release audit
@@ -1 +1 @@
1
- {"version":3,"file":"summary-parse.d.ts","sourceRoot":"","sources":["../../src/domain/summary-parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EACX,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,MAAM,qBAAqB,CAAC;AAK7B,uEAAuE;AACvE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ5E;AAiCD;;;GAGG;AACH,wBAAgB,wBAAwB,CACvC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,YAAY,GAAE,MAA8C,GAC1D,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAuCrB;AAYD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CA8D/D;AAED,0DAA0D;AAC1D,wBAAgB,WAAW,CAC1B,OAAO,EAAE,gBAAgB,GAAG,MAAM,EAClC,IAAI,EAAE,WAAW,GACf,OAAO,GAAG,SAAS,CAGrB;AAED,wBAAgB,UAAU,CACzB,OAAO,EAAE,gBAAgB,GAAG,MAAM,EAClC,IAAI,EAAE,WAAW,GACf,OAAO,CAET;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC5B,OAAO,EAAE,gBAAgB,EACzB,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,MAAM,CAcR;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,WAAW,GAAG,gBAAgB,GACxC,gBAAgB,CAwClB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,EACZ,YAAY,SAAK,GACf,gBAAgB,CAoBlB"}
1
+ {"version":3,"file":"summary-parse.d.ts","sourceRoot":"","sources":["../../src/domain/summary-parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EACX,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,MAAM,qBAAqB,CAAC;AAK7B,uEAAuE;AACvE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ5E;AA2DD;;;GAGG;AACH,wBAAgB,wBAAwB,CACvC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,YAAY,GAAE,MAA8C,GAC1D,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAuCrB;AAYD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CA8D/D;AAED,0DAA0D;AAC1D,wBAAgB,WAAW,CAC1B,OAAO,EAAE,gBAAgB,GAAG,MAAM,EAClC,IAAI,EAAE,WAAW,GACf,OAAO,GAAG,SAAS,CAGrB;AAED,wBAAgB,UAAU,CACzB,OAAO,EAAE,gBAAgB,GAAG,MAAM,EAClC,IAAI,EAAE,WAAW,GACf,OAAO,CAET;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC5B,OAAO,EAAE,gBAAgB,EACzB,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,MAAM,CAcR;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,WAAW,GAAG,gBAAgB,GACxC,gBAAgB,CAwClB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,EACZ,YAAY,SAAK,GACf,gBAAgB,CAoBlB"}
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  } from "@earendil-works/pi-coding-agent";
6
6
 
7
7
  // src/constants.ts
8
- var VERSION = "10.1.3";
8
+ var VERSION = "10.1.5";
9
9
  var OPTIONAL_COMPONENTS = {
10
10
  mnemopi: { name: "@oh-my-pi/pi-mnemopi", version: "18.3.1", enables: "Mnemopi memory store" },
11
11
  bun: { name: "bun", version: "1.4.2", enables: "Mnemopi worker runtime when no Bun 1.3.14+ is on PATH" },
@@ -2916,7 +2916,24 @@ function canonicalHeading(kind) {
2916
2916
  // src/domain/summary-parse.ts
2917
2917
  var HEADING_RE = /^(#{1,3})\s+(.+?)\s*$/;
2918
2918
  function summaryEvidenceLine(value, maxLength) {
2919
- return value.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, " ").replace(/\s+/g, " ").trim().replace(/^(?:(?:#{1,6}|[-*+]|>)\s+)+/, "").slice(0, maxLength).trim();
2919
+ const line = value.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, " ").replace(/\s+/g, " ").trim().replace(/^(?:(?:#{1,6}|[-*+]|>)\s+)+/, "");
2920
+ if (line.length <= maxLength)
2921
+ return line;
2922
+ return cutBeforeSplitPath(line, maxLength).trim();
2923
+ }
2924
+ var PATH_TOKEN_CHAR_RE = /[\w./-]/;
2925
+ function cutBeforeSplitPath(line, max) {
2926
+ const kept = line.slice(0, max);
2927
+ if (!PATH_TOKEN_CHAR_RE.test(line[max] ?? "") || !PATH_TOKEN_CHAR_RE.test(kept.slice(-1))) {
2928
+ return kept;
2929
+ }
2930
+ const tokenStart = kept.search(/[\w./-]+$/);
2931
+ const token = kept.slice(tokenStart) + (line.slice(max).match(/^[\w./-]*/)?.[0] ?? "");
2932
+ if (!/[./]/.test(token))
2933
+ return kept;
2934
+ const lastSlash = kept.lastIndexOf("/");
2935
+ const cut = lastSlash >= tokenStart ? lastSlash + 1 : tokenStart;
2936
+ return cut > 0 ? kept.slice(0, cut) : kept;
2920
2937
  }
2921
2938
  function summaryPathLine(value) {
2922
2939
  return JSON.stringify(value);
@@ -24668,8 +24685,18 @@ function transitionBridge(payload, anchors, anchorLoc) {
24668
24685
  }
24669
24686
  function bridgeFits(payload) {
24670
24687
  const markers = listMarkers(payload);
24671
- const displaceable = markers.filter((m) => m.section === "messages" && !m.owned).length;
24672
- return markers.length - displaceable < MARKER_LIMIT;
24688
+ return markers.length - evictable(markers).length < MARKER_LIMIT;
24689
+ }
24690
+ function evictable(markers) {
24691
+ const foreign = (list) => list.filter((m) => !m.owned);
24692
+ const messages = markers.filter((m) => m.section === "messages");
24693
+ const system = markers.filter((m) => m.section === "system");
24694
+ return [
24695
+ ...foreign(messages.slice(0, -1)),
24696
+ ...foreign(system.slice(0, -1)),
24697
+ ...foreign(markers.filter((m) => m.section === "tools")),
24698
+ ...foreign(system.slice(-1))
24699
+ ];
24673
24700
  }
24674
24701
  function setMarker(payload, ref, control) {
24675
24702
  const block = payload.messages[ref.msgIdx].content[ref.blockIdx];
@@ -24731,7 +24758,7 @@ function countMarkers(payload) {
24731
24758
  function enforceMarkerLimit(payload) {
24732
24759
  let markers = listMarkers(payload);
24733
24760
  while (markers.length > MARKER_LIMIT) {
24734
- const target = markers.find((m) => m.section === "messages" && !m.owned) ?? markers.find((m) => m.section === "tools" && !m.owned) ?? markers.find((m) => m.section === "system" && !m.owned);
24761
+ const target = evictable(markers)[0];
24735
24762
  if (!target)
24736
24763
  break;
24737
24764
  delete blockAt(payload, target).cache_control;
package/dist/rtk.js CHANGED
@@ -198,7 +198,7 @@ class SecretScrubber {
198
198
  }
199
199
 
200
200
  // src/constants.ts
201
- var VERSION = "10.1.3";
201
+ var VERSION = "10.1.5";
202
202
  var OPTIONAL_COMPONENTS = {
203
203
  mnemopi: { name: "@oh-my-pi/pi-mnemopi", version: "18.3.1", enables: "Mnemopi memory store" },
204
204
  bun: { name: "bun", version: "1.4.2", enables: "Mnemopi worker runtime when no Bun 1.3.14+ is on PATH" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-smart-compact",
3
- "version": "10.1.3",
3
+ "version": "10.1.5",
4
4
  "description": "Pi Continuity — context hygiene and session continuity for Pi Coding Agent: recoverable cleanup, checkpoints, memory and verified compaction.",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.4.2",