pi-fold 4.2.5 → 4.2.6
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.
|
@@ -1157,6 +1157,18 @@ export function registerActiveContext(pi: any, options: {
|
|
|
1157
1157
|
}
|
|
1158
1158
|
};
|
|
1159
1159
|
|
|
1160
|
+
// WHAT PI'S CONTEXT EVENT WOULD HAND OVER, BEFORE ONE HAS ARRIVED (2026-10-05). Pi's
|
|
1161
|
+
// ExtensionRunner.emitContext filters role "system" before any handler sees a message;
|
|
1162
|
+
// buildSessionContext does not. A `/fold` before the first context event cut folds from
|
|
1163
|
+
// the unfiltered view in session 01a10161: spans that crossed a system-prompt change
|
|
1164
|
+
// looked broken, and that commit erased 739 of 920 folds.
|
|
1165
|
+
const piContextMessages = (ctx: any): unknown[] | null => {
|
|
1166
|
+
const messages = ctx.sessionManager.buildSessionContext?.()?.messages;
|
|
1167
|
+
return Array.isArray(messages)
|
|
1168
|
+
? messages.filter((message: any) => message?.role !== "system")
|
|
1169
|
+
: null;
|
|
1170
|
+
};
|
|
1171
|
+
|
|
1160
1172
|
const snapshotForEvent = (ctx: any, messages: unknown[]): ActiveContextSnapshot =>
|
|
1161
1173
|
timedDerivation(() => mapActiveContext({
|
|
1162
1174
|
sessionId: ctx.sessionManager.getSessionId(),
|
|
@@ -1352,7 +1364,7 @@ export function registerActiveContext(pi: any, options: {
|
|
|
1352
1364
|
persistence.deltasSinceCheckpoint = restoredPersistence?.deltasSinceCheckpoint ?? 0;
|
|
1353
1365
|
persistence.persistedFoldRecords = restoredPersistence?.records ?? new Map<string, FoldRecordEntry>();
|
|
1354
1366
|
persistence.persistedStateSha256 = restoredPersistence?.stateSha256 ?? semanticStateSha256(durableRestored);
|
|
1355
|
-
const restoredMessages = ctx
|
|
1367
|
+
const restoredMessages = piContextMessages(ctx);
|
|
1356
1368
|
measurements.lastProviderMeasurement = latestProviderContextMeasurement(
|
|
1357
1369
|
Array.isArray(restoredMessages) ? restoredMessages : [],
|
|
1358
1370
|
budgetWindowFor(ctx),
|
|
@@ -3897,6 +3909,26 @@ export function registerActiveContext(pi: any, options: {
|
|
|
3897
3909
|
try { updateStatus(ctx); } catch { }
|
|
3898
3910
|
return undefined;
|
|
3899
3911
|
}
|
|
3912
|
+
// PI CHECKS BEFORE THE FIRST PROMPT, BEFORE ANY CONTEXT EVENT (2026-10-05). After a
|
|
3913
|
+
// context_edit (Pi's own retry recovery writes one per failed attempt) Pi stops trusting
|
|
3914
|
+
// the last provider count and estimates the whole raw transcript, folds unseen: 134% on
|
|
3915
|
+
// session 01a10834, 260% on 01a10161. This used to throw for want of a snapshot, suspend
|
|
3916
|
+
// folding and let native compaction run, which ran Pi out of memory on a 272MB session.
|
|
3917
|
+
// The context event that follows projects and commits on the projection itself, so the
|
|
3918
|
+
// boundary is cancelled and folding stays on.
|
|
3919
|
+
const currentSnapshot = lifecycle.latestSnapshot;
|
|
3920
|
+
if (!currentSnapshot || currentSnapshot.sessionId !== ctx.sessionManager.getSessionId()) {
|
|
3921
|
+
nativeCompaction.lastThresholdDecision = {
|
|
3922
|
+
handled: true,
|
|
3923
|
+
retry: false,
|
|
3924
|
+
reason: `${contextBrand(brandNoun)} blocked stock automatic compaction before the first context event; ` +
|
|
3925
|
+
"the projection is measured when the request is built",
|
|
3926
|
+
compactionReason: reason,
|
|
3927
|
+
nativeCompactionCompleted: false,
|
|
3928
|
+
};
|
|
3929
|
+
try { updateStatus(ctx); } catch { }
|
|
3930
|
+
return { cancel: true };
|
|
3931
|
+
}
|
|
3900
3932
|
let handoff: Record<string, unknown> | null = null;
|
|
3901
3933
|
try {
|
|
3902
3934
|
const snapshot = authoritativeSnapshotFor(ctx);
|
|
@@ -4794,7 +4826,7 @@ export function registerActiveContext(pi: any, options: {
|
|
|
4794
4826
|
if (!persistence.state) persistence.state = emptyActiveContextState(ctx.sessionManager.getSessionId());
|
|
4795
4827
|
const snapshot = lifecycle.latestSnapshot
|
|
4796
4828
|
? authoritativeSnapshotFor(ctx)
|
|
4797
|
-
: snapshotForEvent(ctx, ctx
|
|
4829
|
+
: snapshotForEvent(ctx, piContextMessages(ctx) ?? []);
|
|
4798
4830
|
if (!lifecycle.latestSnapshot) lifecycle.latestSnapshot = snapshot;
|
|
4799
4831
|
const divider = args.indexOf(" -- ");
|
|
4800
4832
|
const selector = (divider >= 0 ? args.slice(0, divider) : args).trim();
|
|
@@ -4904,7 +4936,7 @@ export function registerActiveContext(pi: any, options: {
|
|
|
4904
4936
|
}
|
|
4905
4937
|
const snapshot = lifecycle.latestSnapshot
|
|
4906
4938
|
? authoritativeSnapshotFor(ctx)
|
|
4907
|
-
: snapshotForEvent(ctx, ctx
|
|
4939
|
+
: snapshotForEvent(ctx, piContextMessages(ctx) ?? []);
|
|
4908
4940
|
if (!lifecycle.latestSnapshot) lifecycle.latestSnapshot = snapshot;
|
|
4909
4941
|
if (!persistence.state) throw new Error("The context window is empty; there is nothing to show yet");
|
|
4910
4942
|
|
|
@@ -69,8 +69,15 @@ export function contentDrifted(snapshot: ActiveContextSnapshot, ref: EvidenceRef
|
|
|
69
69
|
return item !== null && item.ref!.sha256 !== ref.sha256;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
// PI NEVER SHOWS AN EXTENSION ITS SYSTEM MESSAGES (2026-10-05). The context event filters
|
|
73
|
+
// role "system" (ExtensionRunner.emitContext), so a system-prompt-change entry has no
|
|
74
|
+
// place in the window and cannot break a span. Folds cut from a view that did include them
|
|
75
|
+
// (a `/fold` before the first context event, session 01a10161) carry such refs; they are
|
|
76
|
+
// skipped here rather than unseating the fold and, at the next commit, its whole subtree.
|
|
72
77
|
export function refsInOrder(snapshot: ActiveContextSnapshot, refs: EvidenceRef[]): number[] | null {
|
|
73
|
-
const
|
|
78
|
+
const placed = refs.filter((ref) => ref.role !== "system");
|
|
79
|
+
if (!placed.length) return null;
|
|
80
|
+
const indices = placed.map((ref) => exactMapped(snapshot, ref)?.index ?? -1);
|
|
74
81
|
if (indices.some((index) => index < 0) || new Set(indices).size !== indices.length) return null;
|
|
75
82
|
for (let index = 1; index < indices.length; index += 1) if (indices[index] !== indices[index - 1] + 1) return null;
|
|
76
83
|
return indices;
|