pi-fold 4.1.3 → 4.1.4
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.
|
@@ -89,6 +89,7 @@ import {
|
|
|
89
89
|
sameStateProjection,
|
|
90
90
|
semanticStateSha256,
|
|
91
91
|
topologySha256,
|
|
92
|
+
adoptDurableFoldRecords,
|
|
92
93
|
} from "./lib/persistence.ts";
|
|
93
94
|
import type { MaterializedStatePersistence } from "./lib/persistence.ts";
|
|
94
95
|
import {
|
|
@@ -2528,6 +2529,11 @@ export function registerActiveContext(pi: any, options: {
|
|
|
2528
2529
|
state: persistence.state!,
|
|
2529
2530
|
generation: generationAtStart,
|
|
2530
2531
|
});
|
|
2532
|
+
const adoption = adoptDurableFoldRecords(nextState.folds, persistence.persistedFoldRecords);
|
|
2533
|
+
if (adoption.adopted.length) {
|
|
2534
|
+
emit("context.adopt", { adopted: adoption.adopted.length, fold_ids: adoption.adopted.slice(0, 64) });
|
|
2535
|
+
return { preparedFold, nextState: { ...nextState, folds: adoption.folds } };
|
|
2536
|
+
}
|
|
2531
2537
|
return { preparedFold, nextState };
|
|
2532
2538
|
};
|
|
2533
2539
|
|
|
@@ -2769,6 +2775,16 @@ export function registerActiveContext(pi: any, options: {
|
|
|
2769
2775
|
clips: [...(result.state.clips ?? []), ...clipAdditions] } };
|
|
2770
2776
|
}
|
|
2771
2777
|
}
|
|
2778
|
+
// A RE-CUT SPAN ADOPTS ITS DURABLE RECORD (persistence.ts, adoptDurableFoldRecords):
|
|
2779
|
+
// a fold minted here under an id the store already holds, with the same source, takes
|
|
2780
|
+
// the record's bytes before the projection is measured, so the persist path finds
|
|
2781
|
+
// equal digests where session 01a06746 found "Conflicting durable active-context
|
|
2782
|
+
// fold" and stopped folding for good.
|
|
2783
|
+
const adoption = adoptDurableFoldRecords(result.state.folds, persistence.persistedFoldRecords);
|
|
2784
|
+
if (adoption.adopted.length) {
|
|
2785
|
+
result = { ...result, state: { ...result.state, folds: adoption.folds } };
|
|
2786
|
+
emit("context.adopt", { adopted: adoption.adopted.length, fold_ids: adoption.adopted.slice(0, 64) });
|
|
2787
|
+
}
|
|
2772
2788
|
persistence.state = result.state;
|
|
2773
2789
|
const bytesAfter = pricedBytes(projectActiveContext(snapshot, persistence.state));
|
|
2774
2790
|
const freedBytes = Math.max(0, bytesBefore - bytesAfter);
|
|
@@ -2804,6 +2820,7 @@ export function registerActiveContext(pi: any, options: {
|
|
|
2804
2820
|
closing_consolidation_marks: closingAdded,
|
|
2805
2821
|
absorbed_wedges: wedges.absorbed.length,
|
|
2806
2822
|
clipped_results: clippedResults,
|
|
2823
|
+
adopted_records: adoption.adopted.length,
|
|
2807
2824
|
freed_bytes: freedBytes,
|
|
2808
2825
|
freed_tokens: estimatedTokens(freedBytes),
|
|
2809
2826
|
rewrite_tokens: rewriteTokens,
|
|
@@ -789,11 +789,44 @@ export function parseActiveContextStateV2(value: unknown, sessionId: string): Ac
|
|
|
789
789
|
return parsed;
|
|
790
790
|
}
|
|
791
791
|
|
|
792
|
+
/**
|
|
793
|
+
* A RE-CUT SPAN ADOPTS ITS DURABLE RECORD (2026-09-04).
|
|
794
|
+
*
|
|
795
|
+
* A fold's id is derived from its parts, so the same span cut twice mints the same id,
|
|
796
|
+
* and a durable record under an id is immutable by design. Those two facts met in
|
|
797
|
+
* session 01a06746: a persistence projection on the first pass after a restart could
|
|
798
|
+
* not seat one consolidation root and dropped it with its 30 children, the spans read
|
|
799
|
+
* as raw, the frontier cut them again, and the re-cut folds differed from their records
|
|
800
|
+
* by 25 bytes of placeholder text. `normalizeFoldsForPersistedRecords` and the persist
|
|
801
|
+
* path both refused the conflict, folding suspended, and every restart walked into the
|
|
802
|
+
* same refusal because the durable state had already lost the folds.
|
|
803
|
+
*
|
|
804
|
+
* The record is the canonical fold for its source. A fold whose id has a record with
|
|
805
|
+
* the SAME kind and SAME source hash takes the record's bytes (brief, provenance,
|
|
806
|
+
* placeholder size, createdAt) and keeps only its own parent link, so the persist path
|
|
807
|
+
* finds equal digests and the session goes on. A record under the same id with a
|
|
808
|
+
* DIFFERENT source is a corrupt store and still refuses by name.
|
|
809
|
+
*/
|
|
810
|
+
export function adoptDurableFoldRecords(
|
|
811
|
+
folds: ActiveFold[],
|
|
812
|
+
records: Map<string, FoldRecordEntry>,
|
|
813
|
+
): { folds: ActiveFold[]; adopted: string[] } {
|
|
814
|
+
const adopted: string[] = [];
|
|
815
|
+
const next = folds.map((fold) => {
|
|
816
|
+
const record = records.get(fold.id);
|
|
817
|
+
if (!record || sameFoldRecordIdentity(fold, record.fold)) return fold;
|
|
818
|
+
if (record.fold.kind !== fold.kind || record.fold.sourceSha256 !== fold.sourceSha256) return fold;
|
|
819
|
+
adopted.push(fold.id);
|
|
820
|
+
return { ...clone(record.fold), parentId: fold.parentId };
|
|
821
|
+
});
|
|
822
|
+
return { folds: next, adopted };
|
|
823
|
+
}
|
|
824
|
+
|
|
792
825
|
export function normalizeFoldsForPersistedRecords(
|
|
793
826
|
folds: ActiveFold[],
|
|
794
827
|
records: Map<string, FoldRecordEntry>,
|
|
795
828
|
): ActiveFold[] {
|
|
796
|
-
const normalized = folds.map((fold) => {
|
|
829
|
+
const normalized = adoptDurableFoldRecords(folds, records).folds.map((fold) => {
|
|
797
830
|
const record = records.get(fold.id);
|
|
798
831
|
if (!record) return clone(fold);
|
|
799
832
|
if (!sameFoldRecordIdentity(fold, record.fold)) {
|