pi-smart-compact 10.2.0 → 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,32 @@
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
+
5
31
  ## [10.2.0] - 2026-10-05
6
32
 
7
33
  ### Release approval
@@ -5,21 +5,23 @@
5
5
  * Pressure used to reach the model only through the human status line and
6
6
  * `smart_context status` results, so the navigation, history and compaction
7
7
  * tools sat idle until a person asked for them. The note rides along with the
8
- * next tool batch (steer) during a turn; when a turn ends in the cleanup band
9
- * it waits for the next prompt instead. One note per band per session,
10
- * re-armed once pressure clears (compaction, trim, rewind). The note is a
11
- * tail custom message, so the cached prefix is untouched.
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
12
  */
13
13
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
14
14
  import type { CompactConfig } from "../types.ts";
15
15
  export declare const ATTENTION_CUSTOM_TYPE = "smart-compact-attention";
16
- type AttentionConfig = Pick<CompactConfig, "contextNavigationEnabled" | "contextGuidanceEnabled" | "toolLoading" | "autoTrigger" | "minContextPercent" | "prepareContextPercent" | "maxContextTokens">;
16
+ type AttentionConfig = Pick<CompactConfig, "contextNavigationEnabled" | "contextGuidanceEnabled" | "toolLoading" | "autoTrigger" | "autoTriggerStrategy" | "minContextPercent" | "prepareContextPercent" | "maxContextTokens">;
17
17
  export interface ContextAttentionDeps {
18
18
  config: () => AttentionConfig;
19
19
  /** Agent-driven context changes are permitted and nothing (pivot, running compaction) takes priority. */
20
20
  canAgentAct: (ctx: ExtensionContext) => boolean;
21
+ /** The same maintenance gate used by history cleanup; prepared work takes priority. */
22
+ canCleanup: (ctx: ExtensionContext) => boolean;
21
23
  /** A lazy group can still be loaded through `smart_tools`. */
22
- reachable: (group: "navigation" | "history") => boolean;
24
+ reachable: (group: "navigation" | "history" | "compaction") => boolean;
23
25
  }
24
26
  export declare function registerContextAttention(pi: Pick<ExtensionAPI, "on" | "sendMessage" | "getActiveTools">, deps: ContextAttentionDeps): void;
25
27
  export {};
@@ -1 +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;AAK/D,KAAK,eAAe,GAAG,IAAI,CAAC,aAAa,EACvC,0BAA0B,GAAG,wBAAwB,GAAG,aAAa,GAAG,aAAa,GACnF,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,8DAA8D;IAC9D,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,KAAK,OAAO,CAAC;CACzD;AAED,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,aAAa,GAAG,gBAAgB,CAAC,EAC/D,IAAI,EAAE,oBAAoB,GACzB,IAAI,CAoCN"}
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":"AAcA,OAAO,KAAK,EAAE,GAAG,EAAW,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EACV,aAAa,EAEb,iBAAiB,EACjB,mBAAmB,EAEpB,MAAM,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAKL,KAAK,UAAU,EAEf,KAAK,WAAW,EAChB,KAAK,WAAW,EACjB,MAAM,6BAA6B,CAAC;AASrC,wFAAwF;AACxF,eAAO,MAAM,yBAAyB,kMAC2J,CAAC;AAQlM,yGAAyG;AACzG,MAAM,MAAM,gBAAgB,GAAG,MAAM,IAAI,EAAE,CAAC;AAE5C,kGAAkG;AAClG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAElE;AAGD,+FAA+F;AAC/F,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,OAAO,KAAK,GAAG,SAAS,GAAG,IAAI,CAEpF;AAED,KAAK,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC;AAE9D,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAOpG;AASD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,mBAAmB,EAAE,EACpC,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAUf;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,MAAM,CAEnF;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,OAAO,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GACrE;IAAE,OAAO,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,OAAO,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,SAAS,aAAa,EAAE,GACtC,OAAO,CAAC,mBAAmB,CAAC,CAgQ9B;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAUjF;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE;IAAE,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,CAAA;CAAE,GAAG,MAAM,CAE/F;AAED,yEAAyE;AACzE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAC5C,YAAY,QAAQ,EAAE,SAAS,aAAa,EAAE,EAQ7C;CACF;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAiBtF;AAKD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAO9E;AAED,wBAAgB,+BAA+B,IAAI,IAAI,CAEtD;AAED,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE;QAAE,SAAS,IAAI,OAAO,EAAE,CAAC;QAAC,UAAU,IAAI,OAAO,EAAE,CAAC;QAAC,YAAY,CAAC,IAAI,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACzG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,EAAE,CAAC,EAAE;QAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;CAC7E;AASD;;;;;;GAMG;AACH,wBAAgB,sBAAsB;IAGlC,OAAO,MAAM;QAAE,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,CAAA;KAAE,GAAG,IAAI;IAWvF,0EAA0E;IAC1E,MAAM,UAAU,OAAO,OAAO,mBAAmB,GAAG,UAAU,GAAG,SAAS;EA8B7E"}
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.2.0";
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;AAmEzC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAyDtE,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,EAAE,EAAE,YAAY,QAomB7D"}
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.2.0";
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,
@@ -16810,6 +16813,7 @@ function createSettledAutoTrigger(options = {}) {
16810
16813
  // src/app/context-attention.ts
16811
16814
  var ATTENTION_CUSTOM_TYPE = "smart-compact-attention";
16812
16815
  var CONTEXT_TOOL_NAME = "smart_context";
16816
+ var COMPACTION_TOOL_NAME = "smart_compact";
16813
16817
  var LOADER_TOOL_NAME = "smart_tools";
16814
16818
  function registerContextAttention(pi, deps) {
16815
16819
  let noted = null;
@@ -16820,12 +16824,12 @@ function registerContextAttention(pi, deps) {
16820
16824
  pi.on("session_before_switch", clear);
16821
16825
  pi.on("session_before_fork", clear);
16822
16826
  pi.on("session_tree", clear);
16823
- pi.on("message_end", (event, ctx) => {
16824
- const message = event.message;
16825
- if (message.role !== "assistant")
16826
- return;
16827
+ pi.on("session_compact", clear);
16828
+ pi.on("model_select", clear);
16829
+ pi.on("session_shutdown", clear);
16830
+ const attention = (ctx) => {
16827
16831
  const settings = deps.config();
16828
- if (!settings.contextNavigationEnabled || !settings.contextGuidanceEnabled || settings.toolLoading === "off")
16832
+ if (!settings.contextGuidanceEnabled || settings.toolLoading === "off")
16829
16833
  return;
16830
16834
  const sessionId = resolveSessionId(ctx);
16831
16835
  const pressure = contextPressure(ctx, settings);
@@ -16837,51 +16841,74 @@ function registerContextAttention(pi, deps) {
16837
16841
  }
16838
16842
  if (noted?.sessionId === sessionId && (noted.band === band || noted.band === "compaction"))
16839
16843
  return;
16840
- if (message.content.some((block) => block.type === "toolCall" && (block.name === NAVIGATION_TOOL_NAME || block.name === CONTEXT_TOOL_NAME)))
16841
- return;
16842
- const midTurn = message.stopReason === "toolUse";
16843
- if (!midTurn && band === "compaction" && settings.autoTrigger)
16844
- return;
16845
16844
  if (!deps.canAgentAct(ctx))
16846
16845
  return;
16847
16846
  const active = new Set(pi.getActiveTools());
16848
- const content = renderAttention(band, pressure.percent, settings, ctx, active, deps.reachable);
16847
+ const content = renderAttention(band, pressure.percent, settings, ctx, active, deps.reachable, deps.canCleanup(ctx));
16849
16848
  if (!content)
16850
16849
  return;
16851
16850
  noted = { sessionId, band };
16852
- pi.sendMessage({ customType: ATTENTION_CUSTOM_TYPE, content, display: true, details: { band, percent: pressure.percent } }, { deliverAs: midTurn ? "steer" : "nextTurn" });
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" });
16853
16867
  });
16854
16868
  }
16855
- function renderAttention(band, percent, settings, ctx, active, reachable) {
16869
+ function renderAttention(band, percent, settings, ctx, active, reachable, canCleanup) {
16856
16870
  const lines = [];
16857
16871
  const load = (group, tool) => active.has(tool) ? "" : reachable(group) && active.has(LOADER_TOOL_NAME) ? ` Load it first: ${LOADER_TOOL_NAME} load ${group}.` : null;
16858
- const navigation = load("navigation", NAVIGATION_TOOL_NAME);
16872
+ const navigation = settings.contextNavigationEnabled ? load("navigation", NAVIGATION_TOOL_NAME) : null;
16859
16873
  const history = load("history", CONTEXT_TOOL_NAME);
16860
16874
  if (navigation !== null) {
16861
- lines.push((band === "compaction" ? `- Anchor now: ${NAVIGATION_TOOL_NAME} anchor with a name and a concise handoff (done / in progress / next step). The summary starts from it and the prompt cache stays warm up to it.` : `- Finishing a unit of work? ${NAVIGATION_TOOL_NAME} anchor with a concise handoff; safe cleanup is queued automatically and the prefix up to the anchor stays cached.`) + navigation);
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}`);
16862
16876
  }
16863
16877
  if (history !== null) {
16864
- const branch = ctx.sessionManager.getBranch();
16865
16878
  let trimmable = 0;
16866
- let blocked = false;
16867
- try {
16868
- const plan = planContextTrim(branch, inspectContext(branch, resolveSessionId(ctx)).checkpoint?.originId, { readerApi: ctx.model?.api });
16869
- blocked = Boolean(plan.blockedReason);
16870
- trimmable = plan.entries.filter((entry) => entry.type === "context_edit").length;
16871
- } catch {
16872
- blocked = true;
16873
- }
16874
- if (!blocked) {
16875
- if (trimmable > 0)
16876
- lines.push(`- ${CONTEXT_TOOL_NAME} trim: ${trimmable} archived tool output${trimmable === 1 ? "" : "s"} eligible now.${history}`);
16877
- lines.push(`- Starting a large read-only detour? ${CONTEXT_TOOL_NAME} checkpoint first, then rewind(report) when done keeps the findings and drops the research.${trimmable > 0 ? "" : history}`);
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 {}
16878
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}`);
16879
16895
  }
16880
16896
  if (!lines.length)
16881
16897
  return null;
16882
16898
  const where = percent === null ? "" : ` ${Math.round(percent)}% of the policy window`;
16883
- const head = band === "compaction" ? `Context attention:${where} (compaction band). ` + (settings.autoTrigger ? "Compaction prepares now and applies when the turn settles." : "Automatic compaction is off here; the user runs /smart-compact.") : `Context attention:${where} (cleanup band). ` + (settings.autoTrigger ? `Automatic compaction prepares at ${settings.minContextPercent}%.` : "Automatic compaction is off here.");
16884
- return `${head}
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}
16885
16912
  ${lines.join(`
16886
16913
  `)}`;
16887
16914
  }
@@ -25090,11 +25117,12 @@ function smartCompactExtension(pi) {
25090
25117
  onContextEdit: (_ctx, kind) => hostCache.noteContextEdit(kind)
25091
25118
  });
25092
25119
  registerArtifactOffload(pi, automaticConfig, () => toolExposure.reachable("history"));
25120
+ const canAutoTrim = (ctx) => toolExposure.reachable("history") && !background.hasWork() && !pendingRef.isPresent(resolveSessionId(ctx)) && !isRunning.isSessionActive(resolveSessionId(ctx));
25093
25121
  const smartContext = registerSmartContextTool(pi, {
25094
25122
  config: automaticConfig,
25095
25123
  isPaused: pivotQueued,
25096
25124
  canAgentMutate: () => policy.snapshot().agentToolAccess !== "disabled",
25097
- canAutoTrim: (ctx) => toolExposure.reachable("history") && !background.hasWork() && !pendingRef.isPresent(resolveSessionId(ctx)) && !isRunning.isSessionActive(resolveSessionId(ctx)),
25125
+ canAutoTrim,
25098
25126
  onContextChange: (ctx) => invalidatePreparation(ctx, "branch"),
25099
25127
  onContextEdit: (_ctx, kind) => hostCache.noteContextEdit(kind),
25100
25128
  onCacheWarm: (ctx, at) => {
@@ -25105,6 +25133,7 @@ function smartCompactExtension(pi) {
25105
25133
  registerContextAttention(pi, {
25106
25134
  config: automaticConfig,
25107
25135
  canAgentAct: (ctx) => policy.snapshot().agentToolAccess !== "disabled" && !pivotQueued(ctx) && !isRunning.isSessionActive(resolveSessionId(ctx)),
25136
+ canCleanup: canAutoTrim,
25108
25137
  reachable: (group) => toolExposure.reachable(group)
25109
25138
  });
25110
25139
  registerSmartCompactCommand(pi, {
package/dist/rtk.js CHANGED
@@ -198,7 +198,7 @@ class SecretScrubber {
198
198
  }
199
199
 
200
200
  // src/constants.ts
201
- var VERSION = "10.2.0";
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. Also enables context attention: one short note to the model when context usage enters the cleanup band and again at the compaction band, naming only the context tools available right now (anchor; checkpoint/rewind and trim when history edits are possible). Re-armed once pressure clears. |
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.2.0",
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",