pi-smart-compact 10.1.5 → 10.2.1

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,60 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [10.2.1] - 2026-10-05
6
+
7
+ ### Release approval
8
+
9
+ - The release owner approved `10.2.1` as a stable patch with a version-specific
10
+ canary exception. Publication remains gated on the deterministic checks for
11
+ this exact candidate. No version-specific applied-canary cohort or live
12
+ provider/signature test exists; offline regressions do not establish cache-hit
13
+ savings or a `PROMOTE` result.
14
+
15
+ ### Fixed
16
+
17
+ - **Native compaction prefix.** Reuse Pi's complete system/tool transcript
18
+ instead of prepending the current prompt and loadout a second time. Legacy
19
+ histories without an initial system message retain their fallback. Real-adapter
20
+ regressions cover initial and repeated native compaction; provider-side
21
+ thinking-signature acceptance is not claimed by these offline tests.
22
+ - **Context attention follows execution gates.** Do not recommend trimming over
23
+ prepared compaction. Recompute prompt-start guidance instead of parking stale
24
+ pressure in `nextTurn`, and describe settled, background and native-hook
25
+ strategies separately. History guidance remains available with navigation off;
26
+ checkpoints no longer promise that a later rewind will be safe. Anchor advice
27
+ does not guarantee cleanup or cache hits, and manual-mode compaction advice
28
+ distinguishes staging from applying. A real offline Pi lifecycle regression
29
+ covers compaction between a completed high-pressure turn and the next prompt.
30
+
31
+ ## [10.2.0] - 2026-10-05
32
+
33
+ ### Release approval
34
+
35
+ - Minor release approved by the release owner after the deterministic gates
36
+ on the exact candidate. No version-specific applied-canary cohort or live
37
+ provider run exists for `10.2.0`; the feature is evidenced by unit tests
38
+ only. The note is gated by `Navigation guide` (`contextGuidanceEnabled`)
39
+ and turns off with it.
40
+
41
+ ### Added
42
+
43
+ - **Context attention.** Context pressure used to reach the model only through
44
+ the human status line and `smart_context status` results, so the anchor,
45
+ checkpoint/rewind, trim and compaction tools sat idle until a person asked
46
+ for them. The extension now sends the model one short note when usage
47
+ enters the cleanup band and one more at the compaction band, naming only
48
+ the actions available right now: `smart_navigation anchor` (with the lazy
49
+ `smart_tools` load step when needed), `smart_context checkpoint`/`rewind`
50
+ and `trim` only when history edits are possible on this model (signed
51
+ Anthropic thinking blocks them), plus whether automatic compaction will
52
+ prepare. Mid-turn the note rides along with the next tool batch; at a turn
53
+ end a cleanup note waits for the next prompt and a compaction note is
54
+ skipped under auto-trigger because settled compaction runs first. One note
55
+ per band per session, re-armed once pressure clears; the note is a tail
56
+ message, so the cached prefix is untouched. Gated by `Navigation guide`
57
+ (`contextGuidanceEnabled`), tool loading and agent tool access.
58
+
5
59
  ## [10.1.5] - 2026-10-05
6
60
 
7
61
  ### Release approval
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Context attention: one short note to the model when context pressure enters
3
+ * a band, naming only the actions that are available right now.
4
+ *
5
+ * Pressure used to reach the model only through the human status line and
6
+ * `smart_context status` results, so the navigation, history and compaction
7
+ * tools sat idle until a person asked for them. The note rides along with the
8
+ * next tool batch (steer) during a turn. Prompt-start notes are computed then,
9
+ * never parked in nextTurn where compaction or permissions can make them stale.
10
+ * One note per band per session, re-armed once pressure clears or the session
11
+ * changes. Notes append to history; they never rewrite the prompt prefix.
12
+ */
13
+ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
14
+ import type { CompactConfig } from "../types.ts";
15
+ export declare const ATTENTION_CUSTOM_TYPE = "smart-compact-attention";
16
+ type AttentionConfig = Pick<CompactConfig, "contextNavigationEnabled" | "contextGuidanceEnabled" | "toolLoading" | "autoTrigger" | "autoTriggerStrategy" | "minContextPercent" | "prepareContextPercent" | "maxContextTokens">;
17
+ export interface ContextAttentionDeps {
18
+ config: () => AttentionConfig;
19
+ /** Agent-driven context changes are permitted and nothing (pivot, running compaction) takes priority. */
20
+ canAgentAct: (ctx: ExtensionContext) => boolean;
21
+ /** The same maintenance gate used by history cleanup; prepared work takes priority. */
22
+ canCleanup: (ctx: ExtensionContext) => boolean;
23
+ /** A lazy group can still be loaded through `smart_tools`. */
24
+ reachable: (group: "navigation" | "history" | "compaction") => boolean;
25
+ }
26
+ export declare function registerContextAttention(pi: Pick<ExtensionAPI, "on" | "sendMessage" | "getActiveTools">, deps: ContextAttentionDeps): void;
27
+ export {};
28
+ //# sourceMappingURL=context-attention.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-attention.d.ts","sourceRoot":"","sources":["../../src/app/context-attention.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,eAAO,MAAM,qBAAqB,4BAA4B,CAAC;AAM/D,KAAK,eAAe,GAAG,IAAI,CAAC,aAAa,EACvC,0BAA0B,GAAG,wBAAwB,GAAG,aAAa,GAAG,aAAa,GAAG,qBAAqB,GAC3G,mBAAmB,GAAG,uBAAuB,GAAG,kBAAkB,CAAC,CAAC;AAExE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,eAAe,CAAC;IAC9B,yGAAyG;IACzG,WAAW,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC;IAChD,uFAAuF;IACvF,UAAU,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC;IAC/C,8DAA8D;IAC9D,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,YAAY,KAAK,OAAO,CAAC;CACxE;AAED,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,aAAa,GAAG,gBAAgB,CAAC,EAC/D,IAAI,EAAE,oBAAoB,GACzB,IAAI,CA2CN"}
@@ -1 +1 @@
1
- {"version":3,"file":"native-compaction.d.ts","sourceRoot":"","sources":["../../src/app/native-compaction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"native-compaction.d.ts","sourceRoot":"","sources":["../../src/app/native-compaction.ts"],"names":[],"mappings":"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"}
@@ -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.5";
11
+ export declare const VERSION = "10.2.1";
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":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEN,KAAK,YAAY,EAEjB,MAAM,iCAAiC,CAAC;AAkEzC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAyDtE,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,EAAE,EAAE,YAAY,QA8lB7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEN,KAAK,YAAY,EAEjB,MAAM,iCAAiC,CAAC;AAmEzC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAyDtE,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,EAAE,EAAE,YAAY,QAumB7D"}
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.5";
8
+ var VERSION = "10.2.1";
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" },
@@ -9304,6 +9304,7 @@ async function attemptNativeCompaction(rc, priorAttempts) {
9304
9304
  };
9305
9305
  }
9306
9306
  const prefix = rc.msgs.slice(0, cut);
9307
+ const messages = prefix.map((entry) => entry.message);
9307
9308
  const prefixTokens = prefix.reduce((sum, entry) => sum + rc.estimator.message(entry.message), 0);
9308
9309
  const totalEstimate = rc.msgs.reduce((sum, entry) => sum + rc.estimator.message(entry.message), 0);
9309
9310
  const retainedTailTokens = Math.max(0, totalEstimate - prefixTokens);
@@ -9337,9 +9338,11 @@ async function attemptNativeCompaction(rc, priorAttempts) {
9337
9338
  nestedRequests++;
9338
9339
  try {
9339
9340
  const stream = rc.ctx.modelRegistry.streamSimple(model, {
9340
- systemPrompt: rc.ctx.getSystemPrompt(),
9341
- messages: prefix.map((entry) => entry.message),
9342
- tools: toolSource()
9341
+ messages,
9342
+ ...messages[0]?.role === "system" ? {} : {
9343
+ systemPrompt: rc.ctx.getSystemPrompt(),
9344
+ tools: toolSource()
9345
+ }
9343
9346
  }, {
9344
9347
  signal: rc.cancellation.signal,
9345
9348
  fetch: wrapper.fetch,
@@ -16807,6 +16810,109 @@ function createSettledAutoTrigger(options = {}) {
16807
16810
  return { request, noteCompaction, clear };
16808
16811
  }
16809
16812
 
16813
+ // src/app/context-attention.ts
16814
+ var ATTENTION_CUSTOM_TYPE = "smart-compact-attention";
16815
+ var CONTEXT_TOOL_NAME = "smart_context";
16816
+ var COMPACTION_TOOL_NAME = "smart_compact";
16817
+ var LOADER_TOOL_NAME = "smart_tools";
16818
+ function registerContextAttention(pi, deps) {
16819
+ let noted = null;
16820
+ const clear = () => {
16821
+ noted = null;
16822
+ };
16823
+ pi.on("session_start", clear);
16824
+ pi.on("session_before_switch", clear);
16825
+ pi.on("session_before_fork", clear);
16826
+ pi.on("session_tree", clear);
16827
+ pi.on("session_compact", clear);
16828
+ pi.on("model_select", clear);
16829
+ pi.on("session_shutdown", clear);
16830
+ const attention = (ctx) => {
16831
+ const settings = deps.config();
16832
+ if (!settings.contextGuidanceEnabled || settings.toolLoading === "off")
16833
+ return;
16834
+ const sessionId = resolveSessionId(ctx);
16835
+ const pressure = contextPressure(ctx, settings);
16836
+ const band = pressure.compaction ? "compaction" : pressure.cleanup ? "cleanup" : null;
16837
+ if (!band) {
16838
+ if (noted?.sessionId === sessionId)
16839
+ noted = null;
16840
+ return;
16841
+ }
16842
+ if (noted?.sessionId === sessionId && (noted.band === band || noted.band === "compaction"))
16843
+ return;
16844
+ if (!deps.canAgentAct(ctx))
16845
+ return;
16846
+ const active = new Set(pi.getActiveTools());
16847
+ const content = renderAttention(band, pressure.percent, settings, ctx, active, deps.reachable, deps.canCleanup(ctx));
16848
+ if (!content)
16849
+ return;
16850
+ noted = { sessionId, band };
16851
+ return { customType: ATTENTION_CUSTOM_TYPE, content, display: true, details: { band, percent: pressure.percent } };
16852
+ };
16853
+ pi.on("before_agent_start", (_event, ctx) => {
16854
+ const message = attention(ctx);
16855
+ if (message)
16856
+ return { message };
16857
+ });
16858
+ pi.on("message_end", (event, ctx) => {
16859
+ const message = event.message;
16860
+ if (message.role !== "assistant" || message.stopReason !== "toolUse")
16861
+ return;
16862
+ if (message.content.some((block) => block.type === "toolCall" && [NAVIGATION_TOOL_NAME, CONTEXT_TOOL_NAME, COMPACTION_TOOL_NAME].includes(block.name)))
16863
+ return;
16864
+ const note = attention(ctx);
16865
+ if (note)
16866
+ pi.sendMessage(note, { deliverAs: "steer" });
16867
+ });
16868
+ }
16869
+ function renderAttention(band, percent, settings, ctx, active, reachable, canCleanup) {
16870
+ const lines = [];
16871
+ const load = (group, tool) => active.has(tool) ? "" : reachable(group) && active.has(LOADER_TOOL_NAME) ? ` Load it first: ${LOADER_TOOL_NAME} load ${group}.` : null;
16872
+ const navigation = settings.contextNavigationEnabled ? load("navigation", NAVIGATION_TOOL_NAME) : null;
16873
+ const history = load("history", CONTEXT_TOOL_NAME);
16874
+ if (navigation !== null) {
16875
+ lines.push(`- Finishing a unit of work? ${NAVIGATION_TOOL_NAME} anchor with a concise handoff (done / in progress / next step). An anchor alone does not reduce context; cleanup depends on safety and preparation gates.${navigation}`);
16876
+ }
16877
+ if (history !== null) {
16878
+ let trimmable = 0;
16879
+ if (canCleanup) {
16880
+ try {
16881
+ const branch = ctx.sessionManager.getBranch();
16882
+ const plan = planContextTrim(branch, inspectContext(branch, resolveSessionId(ctx)).checkpoint?.originId, { readerApi: ctx.model?.api });
16883
+ if (!plan.blockedReason)
16884
+ trimmable = plan.entries.filter((entry) => entry.type === "context_edit").length;
16885
+ } catch {}
16886
+ }
16887
+ if (trimmable > 0)
16888
+ lines.push(`- ${CONTEXT_TOOL_NAME} trim: ${trimmable} archived tool output${trimmable === 1 ? "" : "s"} eligible now.${history}`);
16889
+ lines.push(`- Starting a large read-only detour? ${CONTEXT_TOOL_NAME} checkpoint first; rewind(report) afterward only when status permits. Keep findings and evidence in the report.${trimmable > 0 ? "" : history}`);
16890
+ }
16891
+ if (band === "compaction" && !settings.autoTrigger) {
16892
+ const compaction = load("compaction", COMPACTION_TOOL_NAME);
16893
+ if (compaction !== null)
16894
+ lines.push(`- ${COMPACTION_TOOL_NAME} stages a summary (or reports an existing one); the user runs /compact within its staging TTL to apply it. Staging does not shrink context.${compaction}`);
16895
+ }
16896
+ if (!lines.length)
16897
+ return null;
16898
+ const where = percent === null ? "" : ` ${Math.round(percent)}% of the policy window`;
16899
+ let automatic;
16900
+ if (!settings.autoTrigger)
16901
+ automatic = "Automatic compaction is off here; the user can run /smart-compact.";
16902
+ else if (settings.autoTriggerStrategy === "native-hook")
16903
+ automatic = "Preparation runs when Pi requests compaction; this strategy has no settled trigger.";
16904
+ else if (band === "compaction")
16905
+ automatic = "Automatic compaction is requested when the turn settles if pressure remains.";
16906
+ else {
16907
+ automatic = `Automatic compaction is requested at ${settings.minContextPercent}% when the turn settles.`;
16908
+ if (settings.autoTriggerStrategy === "background")
16909
+ automatic = "Background preparation can start in the cleanup band. " + automatic;
16910
+ }
16911
+ return `Context attention:${where} (${band} band). ${automatic}
16912
+ ${lines.join(`
16913
+ `)}`;
16914
+ }
16915
+
16810
16916
  // src/app/host-cache-ledger.ts
16811
16917
  var FOREIGN_REBUILD_WARN_COUNT = 3;
16812
16918
  var num = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
@@ -25011,11 +25117,12 @@ function smartCompactExtension(pi) {
25011
25117
  onContextEdit: (_ctx, kind) => hostCache.noteContextEdit(kind)
25012
25118
  });
25013
25119
  registerArtifactOffload(pi, automaticConfig, () => toolExposure.reachable("history"));
25120
+ const canAutoTrim = (ctx) => toolExposure.reachable("history") && !background.hasWork() && !pendingRef.isPresent(resolveSessionId(ctx)) && !isRunning.isSessionActive(resolveSessionId(ctx));
25014
25121
  const smartContext = registerSmartContextTool(pi, {
25015
25122
  config: automaticConfig,
25016
25123
  isPaused: pivotQueued,
25017
25124
  canAgentMutate: () => policy.snapshot().agentToolAccess !== "disabled",
25018
- canAutoTrim: (ctx) => toolExposure.reachable("history") && !background.hasWork() && !pendingRef.isPresent(resolveSessionId(ctx)) && !isRunning.isSessionActive(resolveSessionId(ctx)),
25125
+ canAutoTrim,
25019
25126
  onContextChange: (ctx) => invalidatePreparation(ctx, "branch"),
25020
25127
  onContextEdit: (_ctx, kind) => hostCache.noteContextEdit(kind),
25021
25128
  onCacheWarm: (ctx, at) => {
@@ -25023,6 +25130,12 @@ function smartCompactExtension(pi) {
25023
25130
  hostCache.noteCacheWarm(at);
25024
25131
  }
25025
25132
  });
25133
+ registerContextAttention(pi, {
25134
+ config: automaticConfig,
25135
+ canAgentAct: (ctx) => policy.snapshot().agentToolAccess !== "disabled" && !pivotQueued(ctx) && !isRunning.isSessionActive(resolveSessionId(ctx)),
25136
+ canCleanup: canAutoTrim,
25137
+ reachable: (group) => toolExposure.reachable(group)
25138
+ });
25026
25139
  registerSmartCompactCommand(pi, {
25027
25140
  pendingRef,
25028
25141
  runLock: isRunning,
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.5";
201
+ var VERSION = "10.2.1";
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" },
@@ -454,7 +454,7 @@ Settings → **Agent tools & navigation**.
454
454
  | `contextPivotEnabled` | `Return to an anchor` | `true` | Returning to an anchor on a new branch with a required carryover. |
455
455
  | `contextAnchorCacheEnabled` | `Anchor prompt cache` | `true` | Anthropic models: keeps a prompt-cache marker on the newest anchor. |
456
456
  | `contextAnchorStatusEnabled` | `Anchor status` | `true` | Shows the newest anchor on this branch in Pi's footer; display only. |
457
- | `contextGuidanceEnabled` | `Navigation guide` | `true` | Lets you or the agent open the navigation guide on request; it is never added to a request otherwise. |
457
+ | `contextGuidanceEnabled` | `Navigation guide` | `true` | Lets you or the agent open the navigation guide on request; the full guide is never injected automatically. Also enables one short context-attention note per pressure band. Prompt-start advice uses current usage and permissions, not a parked `nextTurn` note. It names reachable tools, shares cleanup's preparation gate, and distinguishes automatic strategies and staging from applying. Checkpoint metadata can remain available when trim/rewind is blocked. Navigation off does not disable history guidance. Re-armed when pressure clears, compaction occurs or the session/model changes. |
458
458
 
459
459
  Group permissions apply in both `lazy` and `eager` modes: `compaction` follows
460
460
  `agentToolAccess`, `memory` needs `contextGraphEnabled` or a non-local
package/docs/guide.md CHANGED
@@ -459,8 +459,9 @@ Settings → **Agent tools & navigation** has the switches: **Session
459
459
  navigation** (off hides the panel and the agent tool; recorded anchors and the
460
460
  other switches are kept), **Search other sessions**, **Return to an anchor**,
461
461
  **Anchor prompt cache** (Anthropic models: keeps a prompt-cache marker on the
462
- newest anchor, so the context before it is read from cache while later turns
463
- change), **Anchor status** (footer, display only) and **Navigation guide**.
462
+ newest anchor so an unchanged prefix can be reused while later turns change;
463
+ hits still depend on provider caching and expiry), **Anchor status** (footer,
464
+ display only) and **Navigation guide**.
464
465
 
465
466
  Legacy `context` tool anchors recorded in earlier sessions stay readable in
466
467
  browse and search.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-smart-compact",
3
- "version": "10.1.5",
3
+ "version": "10.2.1",
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",