@animalabs/context-manager 0.5.2 → 0.5.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.
- package/dist/src/adaptive/index.d.ts +6 -0
- package/dist/src/adaptive/index.d.ts.map +1 -1
- package/dist/src/adaptive/index.js +8 -0
- package/dist/src/adaptive/index.js.map +1 -1
- package/dist/src/adaptive/kv-cache-sim.d.ts +128 -0
- package/dist/src/adaptive/kv-cache-sim.d.ts.map +1 -0
- package/dist/src/adaptive/kv-cache-sim.js +0 -0
- package/dist/src/adaptive/kv-cache-sim.js.map +1 -0
- package/dist/src/adaptive/kv-control.d.ts +152 -0
- package/dist/src/adaptive/kv-control.d.ts.map +1 -0
- package/dist/src/adaptive/kv-control.js +368 -0
- package/dist/src/adaptive/kv-control.js.map +1 -0
- package/dist/src/adaptive/kv-replay.d.ts +76 -0
- package/dist/src/adaptive/kv-replay.d.ts.map +1 -0
- package/dist/src/adaptive/kv-replay.js +175 -0
- package/dist/src/adaptive/kv-replay.js.map +1 -0
- package/dist/src/adaptive/render-offsets.d.ts +61 -0
- package/dist/src/adaptive/render-offsets.d.ts.map +1 -0
- package/dist/src/adaptive/render-offsets.js +88 -0
- package/dist/src/adaptive/render-offsets.js.map +1 -0
- package/dist/src/adaptive/strategies/kv-stable.d.ts +48 -0
- package/dist/src/adaptive/strategies/kv-stable.d.ts.map +1 -0
- package/dist/src/adaptive/strategies/kv-stable.js +102 -0
- package/dist/src/adaptive/strategies/kv-stable.js.map +1 -0
- package/dist/src/adaptive/summary-tree.d.ts +98 -0
- package/dist/src/adaptive/summary-tree.d.ts.map +1 -0
- package/dist/src/adaptive/summary-tree.js +214 -0
- package/dist/src/adaptive/summary-tree.js.map +1 -0
- package/dist/src/context-log.d.ts.map +1 -1
- package/dist/src/context-log.js +7 -2
- package/dist/src/context-log.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/message-store.js +1 -1
- package/dist/src/message-store.js.map +1 -1
- package/dist/src/normalize-tool-messages.d.ts +33 -0
- package/dist/src/normalize-tool-messages.d.ts.map +1 -1
- package/dist/src/normalize-tool-messages.js +59 -0
- package/dist/src/normalize-tool-messages.js.map +1 -1
- package/dist/src/strategies/autobiographical.d.ts +101 -39
- package/dist/src/strategies/autobiographical.d.ts.map +1 -1
- package/dist/src/strategies/autobiographical.js +398 -222
- package/dist/src/strategies/autobiographical.js.map +1 -1
- package/dist/src/types/strategy.d.ts +40 -1
- package/dist/src/types/strategy.d.ts.map +1 -1
- package/dist/src/types/strategy.js +2 -0
- package/dist/src/types/strategy.js.map +1 -1
- package/dist/test/adaptive/kv-cache-sim.test.d.ts +16 -0
- package/dist/test/adaptive/kv-cache-sim.test.d.ts.map +1 -0
- package/dist/test/adaptive/kv-cache-sim.test.js +173 -0
- package/dist/test/adaptive/kv-cache-sim.test.js.map +1 -0
- package/dist/test/adaptive/kv-control.test.d.ts +14 -0
- package/dist/test/adaptive/kv-control.test.d.ts.map +1 -0
- package/dist/test/adaptive/kv-control.test.js +130 -0
- package/dist/test/adaptive/kv-control.test.js.map +1 -0
- package/dist/test/adaptive/kv-replay.test.d.ts +15 -0
- package/dist/test/adaptive/kv-replay.test.d.ts.map +1 -0
- package/dist/test/adaptive/kv-replay.test.js +112 -0
- package/dist/test/adaptive/kv-replay.test.js.map +1 -0
- package/dist/test/adaptive/kv-stable-strategy.test.d.ts +10 -0
- package/dist/test/adaptive/kv-stable-strategy.test.d.ts.map +1 -0
- package/dist/test/adaptive/kv-stable-strategy.test.js +89 -0
- package/dist/test/adaptive/kv-stable-strategy.test.js.map +1 -0
- package/dist/test/adaptive/render-offsets.test.d.ts +11 -0
- package/dist/test/adaptive/render-offsets.test.d.ts.map +1 -0
- package/dist/test/adaptive/render-offsets.test.js +85 -0
- package/dist/test/adaptive/render-offsets.test.js.map +1 -0
- package/dist/test/adaptive/summary-tree.test.d.ts +5 -0
- package/dist/test/adaptive/summary-tree.test.d.ts.map +1 -0
- package/dist/test/adaptive/summary-tree.test.js +72 -0
- package/dist/test/adaptive/summary-tree.test.js.map +1 -0
- package/dist/test/chunker-tool-boundary.test.d.ts +12 -0
- package/dist/test/chunker-tool-boundary.test.d.ts.map +1 -0
- package/dist/test/chunker-tool-boundary.test.js +89 -0
- package/dist/test/chunker-tool-boundary.test.js.map +1 -0
- package/dist/test/compression-shape-invariants.test.d.ts +22 -0
- package/dist/test/compression-shape-invariants.test.d.ts.map +1 -0
- package/dist/test/compression-shape-invariants.test.js +312 -0
- package/dist/test/compression-shape-invariants.test.js.map +1 -0
- package/dist/test/image-strip-render-stats.test.d.ts +2 -0
- package/dist/test/image-strip-render-stats.test.d.ts.map +1 -0
- package/dist/test/image-strip-render-stats.test.js +130 -0
- package/dist/test/image-strip-render-stats.test.js.map +1 -0
- package/dist/test/image-stripping.test.d.ts +13 -0
- package/dist/test/image-stripping.test.d.ts.map +1 -0
- package/dist/test/image-stripping.test.js +104 -0
- package/dist/test/image-stripping.test.js.map +1 -0
- package/dist/test/normalize-tool-messages.test.js +61 -1
- package/dist/test/normalize-tool-messages.test.js.map +1 -1
- package/dist/test/render-stats.test.d.ts +2 -0
- package/dist/test/render-stats.test.d.ts.map +1 -0
- package/dist/test/render-stats.test.js +91 -0
- package/dist/test/render-stats.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/adaptive/index.ts +48 -0
- package/src/adaptive/kv-cache-sim.ts +0 -0
- package/src/adaptive/kv-control.ts +497 -0
- package/src/adaptive/kv-replay.ts +238 -0
- package/src/adaptive/render-offsets.ts +116 -0
- package/src/adaptive/strategies/kv-stable.ts +123 -0
- package/src/adaptive/summary-tree.ts +252 -0
- package/src/context-log.ts +7 -2
- package/src/index.ts +1 -1
- package/src/message-store.ts +1 -1
- package/src/normalize-tool-messages.ts +61 -0
- package/src/strategies/autobiographical.ts +414 -271
- package/src/types/strategy.ts +40 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rendered-unit / offset accounting for the adaptive compiled context.
|
|
3
|
+
*
|
|
4
|
+
* `render.ts` reconstructs content byte-faithfully but exposes no token
|
|
5
|
+
* positions. The V2 best-fit KV term needs them: KV cost is governed by the
|
|
6
|
+
* EARLIEST position at which a new frontier diverges from the previous one —
|
|
7
|
+
* the provider caches the longest byte-identical prefix, so every token after
|
|
8
|
+
* the first divergence is recomputed (`docs/best-fit-frontier-resolution.md`
|
|
9
|
+
* §4, §4.1).
|
|
10
|
+
*
|
|
11
|
+
* `renderLayout` produces the ordered sequence of rendered units (head,
|
|
12
|
+
* per-chunk raw/recall in source order, tail) with cumulative token offsets,
|
|
13
|
+
* matching `MutableFoldingState.computeTokens` exactly:
|
|
14
|
+
* - head/tail are fixed blocks;
|
|
15
|
+
* - pinned chunks render raw (L0) regardless of resolution;
|
|
16
|
+
* - a folded chunk emits its L_k ancestor's recall pair, once per distinct
|
|
17
|
+
* ancestor (siblings share one recall pair);
|
|
18
|
+
* - a resolution whose ancestor summary is missing falls back to raw.
|
|
19
|
+
*
|
|
20
|
+
* Pure and deterministic.
|
|
21
|
+
*/
|
|
22
|
+
import type { ChunkId } from './folding-strategy.js';
|
|
23
|
+
import type { PickerInputs } from './picker.js';
|
|
24
|
+
import type { SummaryTree } from './summary-tree.js';
|
|
25
|
+
/** Resolution map: chunkId → display level (0 = raw). */
|
|
26
|
+
export type Frontier = ReadonlyMap<ChunkId, number>;
|
|
27
|
+
export interface RenderedUnit {
|
|
28
|
+
kind: 'head' | 'raw' | 'recall' | 'tail';
|
|
29
|
+
/**
|
|
30
|
+
* Stable identity for prefix comparison. Two units are byte-identical iff
|
|
31
|
+
* they share (kind, key): 'head'/'tail' for the fixed blocks, the chunk id
|
|
32
|
+
* for a raw shard, the summary id for a recall pair.
|
|
33
|
+
*/
|
|
34
|
+
key: string;
|
|
35
|
+
tokens: number;
|
|
36
|
+
/** Cumulative tokens BEFORE this unit (its start offset in the prefix). */
|
|
37
|
+
offset: number;
|
|
38
|
+
}
|
|
39
|
+
export interface RenderLayout {
|
|
40
|
+
units: RenderedUnit[];
|
|
41
|
+
totalTokens: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build the ordered rendered-unit layout for a frontier. `totalTokens` equals
|
|
45
|
+
* `MutableFoldingState.computeTokens` for the same resolutions.
|
|
46
|
+
*/
|
|
47
|
+
export declare function renderLayout(inputs: PickerInputs, tree: SummaryTree, frontier: Frontier): RenderLayout;
|
|
48
|
+
/**
|
|
49
|
+
* Earliest index at which two unit sequences differ (by kind+key).
|
|
50
|
+
* Returns -1 when the sequences are identical; otherwise the first differing
|
|
51
|
+
* index (which may be `min(len)` when one is a strict prefix of the other).
|
|
52
|
+
*/
|
|
53
|
+
export declare function earliestDivergenceIndex(a: RenderedUnit[], b: RenderedUnit[]): number;
|
|
54
|
+
/**
|
|
55
|
+
* KV cost of moving from `prev` to `next`: the number of tokens in `next` that
|
|
56
|
+
* must be recomputed — everything from the earliest divergence onward. 0 when
|
|
57
|
+
* `next`'s units are an exact prefix of (or identical to) `prev`'s, since the
|
|
58
|
+
* whole of `next` is then a cached prefix.
|
|
59
|
+
*/
|
|
60
|
+
export declare function kvCost(prev: RenderLayout, next: RenderLayout): number;
|
|
61
|
+
//# sourceMappingURL=render-offsets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-offsets.d.ts","sourceRoot":"","sources":["../../../src/adaptive/render-offsets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAa,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,yDAAyD;AACzD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACzC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,QAAQ,GACjB,YAAY,CAkCd;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,YAAY,EAAE,GAAG,MAAM,CAMpF;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAKrE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rendered-unit / offset accounting for the adaptive compiled context.
|
|
3
|
+
*
|
|
4
|
+
* `render.ts` reconstructs content byte-faithfully but exposes no token
|
|
5
|
+
* positions. The V2 best-fit KV term needs them: KV cost is governed by the
|
|
6
|
+
* EARLIEST position at which a new frontier diverges from the previous one —
|
|
7
|
+
* the provider caches the longest byte-identical prefix, so every token after
|
|
8
|
+
* the first divergence is recomputed (`docs/best-fit-frontier-resolution.md`
|
|
9
|
+
* §4, §4.1).
|
|
10
|
+
*
|
|
11
|
+
* `renderLayout` produces the ordered sequence of rendered units (head,
|
|
12
|
+
* per-chunk raw/recall in source order, tail) with cumulative token offsets,
|
|
13
|
+
* matching `MutableFoldingState.computeTokens` exactly:
|
|
14
|
+
* - head/tail are fixed blocks;
|
|
15
|
+
* - pinned chunks render raw (L0) regardless of resolution;
|
|
16
|
+
* - a folded chunk emits its L_k ancestor's recall pair, once per distinct
|
|
17
|
+
* ancestor (siblings share one recall pair);
|
|
18
|
+
* - a resolution whose ancestor summary is missing falls back to raw.
|
|
19
|
+
*
|
|
20
|
+
* Pure and deterministic.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Build the ordered rendered-unit layout for a frontier. `totalTokens` equals
|
|
24
|
+
* `MutableFoldingState.computeTokens` for the same resolutions.
|
|
25
|
+
*/
|
|
26
|
+
export function renderLayout(inputs, tree, frontier) {
|
|
27
|
+
const units = [];
|
|
28
|
+
let offset = 0;
|
|
29
|
+
const push = (kind, key, tokens) => {
|
|
30
|
+
units.push({ kind, key, tokens, offset });
|
|
31
|
+
offset += tokens;
|
|
32
|
+
};
|
|
33
|
+
if (inputs.headTokens > 0)
|
|
34
|
+
push('head', 'head', inputs.headTokens);
|
|
35
|
+
const ordered = [...inputs.chunks].sort((a, b) => a.sequence - b.sequence);
|
|
36
|
+
const renderedSummaries = new Set();
|
|
37
|
+
for (const c of ordered) {
|
|
38
|
+
if (inputs.headChunkIds.has(c.id) || inputs.tailChunkIds.has(c.id))
|
|
39
|
+
continue;
|
|
40
|
+
const effective = c.pinned ? 0 : frontier.get(c.id) ?? 0;
|
|
41
|
+
if (effective === 0) {
|
|
42
|
+
push('raw', c.id, c.rawTokens);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const ancestor = tree.ancestorAt(c.id, effective);
|
|
46
|
+
if (!ancestor) {
|
|
47
|
+
// Resolution set but summary missing — render raw (renderer makes the
|
|
48
|
+
// same call). Matches computeTokens' fallback.
|
|
49
|
+
push('raw', c.id, c.rawTokens);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (renderedSummaries.has(ancestor.id))
|
|
53
|
+
continue; // sibling shares the pair
|
|
54
|
+
renderedSummaries.add(ancestor.id);
|
|
55
|
+
push('recall', ancestor.id, ancestor.recallTokens);
|
|
56
|
+
}
|
|
57
|
+
if (inputs.tailTokens > 0)
|
|
58
|
+
push('tail', 'tail', inputs.tailTokens);
|
|
59
|
+
return { units, totalTokens: offset };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Earliest index at which two unit sequences differ (by kind+key).
|
|
63
|
+
* Returns -1 when the sequences are identical; otherwise the first differing
|
|
64
|
+
* index (which may be `min(len)` when one is a strict prefix of the other).
|
|
65
|
+
*/
|
|
66
|
+
export function earliestDivergenceIndex(a, b) {
|
|
67
|
+
const n = Math.min(a.length, b.length);
|
|
68
|
+
for (let i = 0; i < n; i++) {
|
|
69
|
+
if (a[i].kind !== b[i].kind || a[i].key !== b[i].key)
|
|
70
|
+
return i;
|
|
71
|
+
}
|
|
72
|
+
return a.length === b.length ? -1 : n;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* KV cost of moving from `prev` to `next`: the number of tokens in `next` that
|
|
76
|
+
* must be recomputed — everything from the earliest divergence onward. 0 when
|
|
77
|
+
* `next`'s units are an exact prefix of (or identical to) `prev`'s, since the
|
|
78
|
+
* whole of `next` is then a cached prefix.
|
|
79
|
+
*/
|
|
80
|
+
export function kvCost(prev, next) {
|
|
81
|
+
const d = earliestDivergenceIndex(prev.units, next.units);
|
|
82
|
+
if (d === -1)
|
|
83
|
+
return 0; // identical
|
|
84
|
+
if (d >= next.units.length)
|
|
85
|
+
return 0; // next is a prefix of prev → fully cached
|
|
86
|
+
return next.totalTokens - next.units[d].offset;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=render-offsets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-offsets.js","sourceRoot":"","sources":["../../../src/adaptive/render-offsets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KvStableStrategy — the KV-stable context controller plugged into the existing
|
|
3
|
+
* picker (see `docs/kv-stable-context-control.md`).
|
|
4
|
+
*
|
|
5
|
+
* Same "solve-once-then-walk" bridge as `BestFitStrategy`: on the first
|
|
6
|
+
* `selectNextFold` it computes a target frontier with `planControlledFrontier`
|
|
7
|
+
* (the *same* policy the replay harness measures), memoizes it, then emits one
|
|
8
|
+
* `raise`/`lower` op per call to walk the live state toward it, returning `null`
|
|
9
|
+
* once reached. The picker already applies raise/lower — no picker change.
|
|
10
|
+
*
|
|
11
|
+
* Unlike `BestFitStrategy` (which maximizes value − λ·KVcost over a half-life
|
|
12
|
+
* recency model), this minimizes real prefix churn directly: it holds the flat
|
|
13
|
+
* zone (head/tail/pinned) raw, never folds locked chunks, and sheds the foldable
|
|
14
|
+
* middle oldest-first/leveled under a per-turn divergence **reach cap** (the
|
|
15
|
+
* perturbation cap P), bounded by per-chunk log-age saliency caps, yielding the
|
|
16
|
+
* reach cap only as far as needed to stay under the hard wall (`totalBudget`).
|
|
17
|
+
* No λ, no recency half-life.
|
|
18
|
+
*
|
|
19
|
+
* Like `BestFitStrategy`, it does not emit `produce` ops — deeper folding than
|
|
20
|
+
* has been produced is the speculative pre-producer's job; the controller only
|
|
21
|
+
* targets levels whose summaries already exist. Deterministic.
|
|
22
|
+
*/
|
|
23
|
+
import type { FoldingStrategy, FoldingState, FoldingBudget, FoldOp, ChunkId } from '../folding-strategy.js';
|
|
24
|
+
import type { PickerInputs } from '../picker.js';
|
|
25
|
+
export interface KvStableOptions {
|
|
26
|
+
/** Per-turn divergence reach — the structural perturbation cap P, in tokens.
|
|
27
|
+
* Smaller = gentler per-turn KV churn (shallow divergence) but less efficient
|
|
28
|
+
* compression. Exceeded only to stay under the hard wall. Default: the hard
|
|
29
|
+
* budget (effectively unbounded within the window). */
|
|
30
|
+
reachTokens?: number;
|
|
31
|
+
/** Base-k summary grouping (matches the strategy's mergeThreshold). Default 6. */
|
|
32
|
+
mergeThreshold?: number;
|
|
33
|
+
}
|
|
34
|
+
export declare class KvStableStrategy implements FoldingStrategy {
|
|
35
|
+
readonly name = "kv-stable";
|
|
36
|
+
private readonly inputs;
|
|
37
|
+
private readonly opts;
|
|
38
|
+
private readonly fPrev;
|
|
39
|
+
private target;
|
|
40
|
+
constructor(inputs: PickerInputs, opts?: KvStableOptions);
|
|
41
|
+
selectNextFold(state: FoldingState, budget: FoldingBudget): FoldOp | null;
|
|
42
|
+
/** Target frontier this run is walking toward (null before the first call). */
|
|
43
|
+
targetFrontier(): ReadonlyMap<ChunkId, number> | null;
|
|
44
|
+
private solve;
|
|
45
|
+
/** Emit one op moving the live state toward the target frontier. */
|
|
46
|
+
private nextOp;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=kv-stable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv-stable.d.ts","sourceRoot":"","sources":["../../../../src/adaptive/strategies/kv-stable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,aAAa,EACb,MAAM,EACN,OAAO,EACR,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,MAAM,WAAW,eAAe;IAC9B;;;4DAGwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,gBAAiB,YAAW,eAAe;IACtD,QAAQ,CAAC,IAAI,eAAe;IAE5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,MAAM,CAAqC;gBAEvC,MAAM,EAAE,YAAY,EAAE,IAAI,GAAE,eAAoB;IAM5D,cAAc,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI;IAKzE,+EAA+E;IAC/E,cAAc,IAAI,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,IAAI;IAIrD,OAAO,CAAC,KAAK;IAkCb,oEAAoE;IACpE,OAAO,CAAC,MAAM;CAmBf"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KvStableStrategy — the KV-stable context controller plugged into the existing
|
|
3
|
+
* picker (see `docs/kv-stable-context-control.md`).
|
|
4
|
+
*
|
|
5
|
+
* Same "solve-once-then-walk" bridge as `BestFitStrategy`: on the first
|
|
6
|
+
* `selectNextFold` it computes a target frontier with `planControlledFrontier`
|
|
7
|
+
* (the *same* policy the replay harness measures), memoizes it, then emits one
|
|
8
|
+
* `raise`/`lower` op per call to walk the live state toward it, returning `null`
|
|
9
|
+
* once reached. The picker already applies raise/lower — no picker change.
|
|
10
|
+
*
|
|
11
|
+
* Unlike `BestFitStrategy` (which maximizes value − λ·KVcost over a half-life
|
|
12
|
+
* recency model), this minimizes real prefix churn directly: it holds the flat
|
|
13
|
+
* zone (head/tail/pinned) raw, never folds locked chunks, and sheds the foldable
|
|
14
|
+
* middle oldest-first/leveled under a per-turn divergence **reach cap** (the
|
|
15
|
+
* perturbation cap P), bounded by per-chunk log-age saliency caps, yielding the
|
|
16
|
+
* reach cap only as far as needed to stay under the hard wall (`totalBudget`).
|
|
17
|
+
* No λ, no recency half-life.
|
|
18
|
+
*
|
|
19
|
+
* Like `BestFitStrategy`, it does not emit `produce` ops — deeper folding than
|
|
20
|
+
* has been produced is the speculative pre-producer's job; the controller only
|
|
21
|
+
* targets levels whose summaries already exist. Deterministic.
|
|
22
|
+
*/
|
|
23
|
+
import { SummaryTree } from '../summary-tree.js';
|
|
24
|
+
import { planControlledFrontier } from '../kv-control.js';
|
|
25
|
+
export class KvStableStrategy {
|
|
26
|
+
name = 'kv-stable';
|
|
27
|
+
inputs;
|
|
28
|
+
opts;
|
|
29
|
+
fPrev;
|
|
30
|
+
target = null;
|
|
31
|
+
constructor(inputs, opts = {}) {
|
|
32
|
+
this.inputs = inputs;
|
|
33
|
+
this.opts = opts;
|
|
34
|
+
this.fPrev = new Map(inputs.chunks.map((c) => [c.id, c.currentResolution]));
|
|
35
|
+
}
|
|
36
|
+
selectNextFold(state, budget) {
|
|
37
|
+
if (!this.target)
|
|
38
|
+
this.target = this.solve(budget);
|
|
39
|
+
return this.nextOp(state);
|
|
40
|
+
}
|
|
41
|
+
/** Target frontier this run is walking toward (null before the first call). */
|
|
42
|
+
targetFrontier() {
|
|
43
|
+
return this.target;
|
|
44
|
+
}
|
|
45
|
+
solve(budget) {
|
|
46
|
+
const tree = new SummaryTree(this.inputs);
|
|
47
|
+
// Flat zone (forced raw, never folded): head, tail, pinned. Frozen (kept at
|
|
48
|
+
// their carried resolution, never folded): locked.
|
|
49
|
+
const rawZone = new Set();
|
|
50
|
+
const frozen = new Set();
|
|
51
|
+
let now = 0;
|
|
52
|
+
for (const c of this.inputs.chunks) {
|
|
53
|
+
if (c.sequence > now)
|
|
54
|
+
now = c.sequence;
|
|
55
|
+
if (this.inputs.headChunkIds.has(c.id) || this.inputs.tailChunkIds.has(c.id) || c.pinned) {
|
|
56
|
+
rawZone.add(c.id);
|
|
57
|
+
}
|
|
58
|
+
else if (c.lockedByAgent) {
|
|
59
|
+
frozen.add(c.id);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return planControlledFrontier(this.inputs, tree, {
|
|
63
|
+
previous: this.fPrev,
|
|
64
|
+
// Bidirectional within the slack band: fold when over the hard budget,
|
|
65
|
+
// un-fold to use headroom when under the soft target. Both reach-bounded;
|
|
66
|
+
// [targetBudget, totalBudget] is the quiet dead band.
|
|
67
|
+
foldAtTokens: budget.totalBudget,
|
|
68
|
+
expandAtTokens: budget.targetBudget,
|
|
69
|
+
targetTokens: budget.targetBudget,
|
|
70
|
+
windowTokens: budget.totalBudget,
|
|
71
|
+
reachTokens: this.opts.reachTokens,
|
|
72
|
+
rawZone,
|
|
73
|
+
frozen,
|
|
74
|
+
now,
|
|
75
|
+
mergeThreshold: this.opts.mergeThreshold,
|
|
76
|
+
}).resolutions;
|
|
77
|
+
}
|
|
78
|
+
/** Emit one op moving the live state toward the target frontier. */
|
|
79
|
+
nextOp(state) {
|
|
80
|
+
const target = this.target;
|
|
81
|
+
for (const c of state.chunks()) {
|
|
82
|
+
if (c.inHead || c.inTail || c.pinned || c.lockedByAgent)
|
|
83
|
+
continue;
|
|
84
|
+
const cur = c.currentResolution;
|
|
85
|
+
const tgt = target.get(c.id) ?? 0;
|
|
86
|
+
if (cur === tgt)
|
|
87
|
+
continue;
|
|
88
|
+
if (cur < tgt) {
|
|
89
|
+
const summary = c.ancestorAt(tgt);
|
|
90
|
+
if (!summary)
|
|
91
|
+
continue; // unrealizable target (summary not produced) — skip
|
|
92
|
+
return { kind: 'raise', groupRoot: summary.id };
|
|
93
|
+
}
|
|
94
|
+
const summary = c.ancestorAt(cur);
|
|
95
|
+
if (!summary)
|
|
96
|
+
continue;
|
|
97
|
+
return { kind: 'lower', groupRoot: summary.id };
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=kv-stable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv-stable.js","sourceRoot":"","sources":["../../../../src/adaptive/strategies/kv-stable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAUH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAY1D,MAAM,OAAO,gBAAgB;IAClB,IAAI,GAAG,WAAW,CAAC;IAEX,MAAM,CAAe;IACrB,IAAI,CAAkB;IACtB,KAAK,CAAuB;IACrC,MAAM,GAAgC,IAAI,CAAC;IAEnD,YAAY,MAAoB,EAAE,OAAwB,EAAE;QAC1D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,cAAc,CAAC,KAAmB,EAAE,MAAqB;QACvD,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,+EAA+E;IAC/E,cAAc;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,MAAqB;QACjC,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE1C,4EAA4E;QAC5E,mDAAmD;QACnD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAW,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAW,CAAC;QAClC,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,CAAC,QAAQ,GAAG,GAAG;gBAAE,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC;YACvC,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;gBACzF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpB,CAAC;iBAAM,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAED,OAAO,sBAAsB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE;YAC/C,QAAQ,EAAE,IAAI,CAAC,KAAK;YACpB,uEAAuE;YACvE,0EAA0E;YAC1E,sDAAsD;YACtD,YAAY,EAAE,MAAM,CAAC,WAAW;YAChC,cAAc,EAAE,MAAM,CAAC,YAAY;YACnC,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,YAAY,EAAE,MAAM,CAAC,WAAW;YAChC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;YAClC,OAAO;YACP,MAAM;YACN,GAAG;YACH,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc;SACzC,CAAC,CAAC,WAAW,CAAC;IACjB,CAAC;IAED,oEAAoE;IAC5D,MAAM,CAAC,KAAmB;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAO,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,aAAa;gBAAE,SAAS;YAClE,MAAM,GAAG,GAAG,CAAC,CAAC,iBAAiB,CAAC;YAChC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,GAAG,KAAK,GAAG;gBAAE,SAAS;YAE1B,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;gBACd,MAAM,OAAO,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;gBAClC,IAAI,CAAC,OAAO;oBAAE,SAAS,CAAC,oDAAoD;gBAC5E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;YAClD,CAAC;YACD,MAAM,OAAO,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;QAClD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SummaryTree — a typed, structural view over the adaptive summary forest.
|
|
3
|
+
*
|
|
4
|
+
* Built from PickerInputs (chunks + summaries + per-summary recall-pair token
|
|
5
|
+
* counts). Provides the navigation a frontier solver needs — ancestor chains,
|
|
6
|
+
* recall-pair token costs, leaf coverage, root/children traversal — with NO
|
|
7
|
+
* rendering or resolution state. Pure and deterministic.
|
|
8
|
+
*
|
|
9
|
+
* Structure mirrors the model the picker already uses:
|
|
10
|
+
* - `chunk.l1Id` + the `SummaryEntry.parentId` chain define the upward path.
|
|
11
|
+
* - `SummaryEntry.sourceLevel === 0` means `sourceIds` are leaf (message) ids;
|
|
12
|
+
* otherwise they are child summary ids.
|
|
13
|
+
* - A folded node's token cost is its recall-pair size
|
|
14
|
+
* (`recallPairTokens` ?? `SummaryEntry.tokens`) — matching
|
|
15
|
+
* `MutableFoldingState.computeTokens`.
|
|
16
|
+
*
|
|
17
|
+
* This is the substrate for the V2 best-fit tree-knapsack DP. See
|
|
18
|
+
* `docs/best-fit-frontier-resolution.md` §3, §6, §11.
|
|
19
|
+
*/
|
|
20
|
+
import type { ChunkId, SummaryId } from './folding-strategy.js';
|
|
21
|
+
import type { PickerInputs } from './picker.js';
|
|
22
|
+
/** A raw chunk (resolution 0) — a leaf of the summary forest. */
|
|
23
|
+
export interface LeafNode {
|
|
24
|
+
kind: 'leaf';
|
|
25
|
+
chunkId: ChunkId;
|
|
26
|
+
/** Position in source order (lower = older). */
|
|
27
|
+
sequence: number;
|
|
28
|
+
rawTokens: number;
|
|
29
|
+
/** L1 summary covering this leaf, if any. */
|
|
30
|
+
l1Id?: SummaryId;
|
|
31
|
+
}
|
|
32
|
+
/** An L_k summary node covering a contiguous range of leaves. */
|
|
33
|
+
export interface SummaryNode {
|
|
34
|
+
kind: 'summary';
|
|
35
|
+
id: SummaryId;
|
|
36
|
+
level: number;
|
|
37
|
+
/** Rendered tokens of this node's recall pair (the cost of folding to it). */
|
|
38
|
+
recallTokens: number;
|
|
39
|
+
/** Immediate children: leaf chunk ids (when childrenAreLeaves) or summary ids. */
|
|
40
|
+
childIds: string[];
|
|
41
|
+
/** True when childIds are leaf chunk ids (sourceLevel === 0). */
|
|
42
|
+
childrenAreLeaves: boolean;
|
|
43
|
+
/** All covered leaf chunk ids, recursively, in source order. */
|
|
44
|
+
leafChunkIds: ChunkId[];
|
|
45
|
+
/** Min/max source sequence of covered leaves (−1 if none resolve). */
|
|
46
|
+
firstSequence: number;
|
|
47
|
+
lastSequence: number;
|
|
48
|
+
sourceRange: {
|
|
49
|
+
first: string;
|
|
50
|
+
last: string;
|
|
51
|
+
};
|
|
52
|
+
/** Parent summary id, if a higher level has been produced. */
|
|
53
|
+
parentId?: SummaryId;
|
|
54
|
+
}
|
|
55
|
+
export type TreeNode = LeafNode | SummaryNode;
|
|
56
|
+
/** Token cost of rendering a node collapsed: raw for a leaf, recall for a summary. */
|
|
57
|
+
export declare function nodeTokens(node: TreeNode): number;
|
|
58
|
+
export declare class SummaryTree {
|
|
59
|
+
private readonly leaves;
|
|
60
|
+
private readonly nodes;
|
|
61
|
+
private readonly summaries;
|
|
62
|
+
private readonly recallPairTokens;
|
|
63
|
+
private readonly leafSeq;
|
|
64
|
+
private rootCache;
|
|
65
|
+
constructor(inputs: PickerInputs);
|
|
66
|
+
/** All leaf nodes in source order (oldest first). */
|
|
67
|
+
orderedLeaves(): LeafNode[];
|
|
68
|
+
/** All summary nodes (unordered). */
|
|
69
|
+
allSummaries(): SummaryNode[];
|
|
70
|
+
leaf(chunkId: ChunkId): LeafNode | null;
|
|
71
|
+
summary(id: SummaryId): SummaryNode | null;
|
|
72
|
+
/** Recall-pair tokens for a summary, or null if unknown. */
|
|
73
|
+
recallTokens(id: SummaryId): number | null;
|
|
74
|
+
/** Immediate children of a summary node (leaves or sub-summaries). */
|
|
75
|
+
children(node: SummaryNode): TreeNode[];
|
|
76
|
+
/** All leaf chunk ids under a summary, in source order. */
|
|
77
|
+
leavesUnder(id: SummaryId): ChunkId[];
|
|
78
|
+
/**
|
|
79
|
+
* The L_level ancestor summary of a chunk, or null if not present. Matches
|
|
80
|
+
* `MutableFoldingState.ancestorAt` (walks the parentId chain from l1Id).
|
|
81
|
+
*/
|
|
82
|
+
ancestorAt(chunkId: ChunkId, level: number): SummaryNode | null;
|
|
83
|
+
/** Highest level k for which a summary covering this chunk exists (0 = none). */
|
|
84
|
+
maxLevel(chunkId: ChunkId): number;
|
|
85
|
+
/**
|
|
86
|
+
* Forest roots over all chunks: top-level summaries (no parent present in the
|
|
87
|
+
* map) plus any leaf not covered by an L1. Each leaf belongs to exactly one
|
|
88
|
+
* root's subtree. Deterministically ordered by source sequence.
|
|
89
|
+
*/
|
|
90
|
+
roots(): TreeNode[];
|
|
91
|
+
private buildNode;
|
|
92
|
+
/** Walk down to leaf chunk ids; sourceLevel 0 => sourceIds are leaves.
|
|
93
|
+
* Deduplicates leaves and guards against revisiting a summary, so a chunk
|
|
94
|
+
* reachable via multiple branches is counted once (real chronicles can have
|
|
95
|
+
* such overlap; double-counting breaks range/contiguity and value math). */
|
|
96
|
+
private collectLeafIds;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=summary-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary-tree.d.ts","sourceRoot":"","sources":["../../../src/adaptive/summary-tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,iEAAiE;AACjE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,SAAS,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,YAAY,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gEAAgE;IAChE,YAAY,EAAE,OAAO,EAAE,CAAC;IACxB,sEAAsE;IACtE,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE9C,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAEjD;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAiC;IAClE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,SAAS,CAA2B;gBAEhC,MAAM,EAAE,YAAY;IAqBhC,qDAAqD;IACrD,aAAa,IAAI,QAAQ,EAAE;IAI3B,qCAAqC;IACrC,YAAY,IAAI,WAAW,EAAE;IAI7B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI;IAIvC,OAAO,CAAC,EAAE,EAAE,SAAS,GAAG,WAAW,GAAG,IAAI;IAI1C,4DAA4D;IAC5D,YAAY,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI;IAI1C,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,QAAQ,EAAE;IAgBvC,2DAA2D;IAC3D,WAAW,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,EAAE;IAIrC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAY/D,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAalC;;;;OAIG;IACH,KAAK,IAAI,QAAQ,EAAE;IAoBnB,OAAO,CAAC,SAAS;IAyBjB;;;iFAG6E;IAC7E,OAAO,CAAC,cAAc;CAyBvB"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SummaryTree — a typed, structural view over the adaptive summary forest.
|
|
3
|
+
*
|
|
4
|
+
* Built from PickerInputs (chunks + summaries + per-summary recall-pair token
|
|
5
|
+
* counts). Provides the navigation a frontier solver needs — ancestor chains,
|
|
6
|
+
* recall-pair token costs, leaf coverage, root/children traversal — with NO
|
|
7
|
+
* rendering or resolution state. Pure and deterministic.
|
|
8
|
+
*
|
|
9
|
+
* Structure mirrors the model the picker already uses:
|
|
10
|
+
* - `chunk.l1Id` + the `SummaryEntry.parentId` chain define the upward path.
|
|
11
|
+
* - `SummaryEntry.sourceLevel === 0` means `sourceIds` are leaf (message) ids;
|
|
12
|
+
* otherwise they are child summary ids.
|
|
13
|
+
* - A folded node's token cost is its recall-pair size
|
|
14
|
+
* (`recallPairTokens` ?? `SummaryEntry.tokens`) — matching
|
|
15
|
+
* `MutableFoldingState.computeTokens`.
|
|
16
|
+
*
|
|
17
|
+
* This is the substrate for the V2 best-fit tree-knapsack DP. See
|
|
18
|
+
* `docs/best-fit-frontier-resolution.md` §3, §6, §11.
|
|
19
|
+
*/
|
|
20
|
+
import { getSummaryParentId } from '../types/strategy.js';
|
|
21
|
+
/** Token cost of rendering a node collapsed: raw for a leaf, recall for a summary. */
|
|
22
|
+
export function nodeTokens(node) {
|
|
23
|
+
return node.kind === 'leaf' ? node.rawTokens : node.recallTokens;
|
|
24
|
+
}
|
|
25
|
+
export class SummaryTree {
|
|
26
|
+
leaves = new Map();
|
|
27
|
+
nodes = new Map();
|
|
28
|
+
summaries;
|
|
29
|
+
recallPairTokens;
|
|
30
|
+
leafSeq = new Map();
|
|
31
|
+
rootCache = null;
|
|
32
|
+
constructor(inputs) {
|
|
33
|
+
this.summaries = inputs.summaries;
|
|
34
|
+
this.recallPairTokens = inputs.recallPairTokens ?? new Map();
|
|
35
|
+
for (const c of inputs.chunks) {
|
|
36
|
+
this.leafSeq.set(c.id, c.sequence);
|
|
37
|
+
this.leaves.set(c.id, {
|
|
38
|
+
kind: 'leaf',
|
|
39
|
+
chunkId: c.id,
|
|
40
|
+
sequence: c.sequence,
|
|
41
|
+
rawTokens: c.rawTokens,
|
|
42
|
+
l1Id: c.l1Id,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
for (const [, s] of this.summaries) {
|
|
46
|
+
this.nodes.set(s.id, this.buildNode(s));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ---- node access ----
|
|
50
|
+
/** All leaf nodes in source order (oldest first). */
|
|
51
|
+
orderedLeaves() {
|
|
52
|
+
return [...this.leaves.values()].sort((a, b) => a.sequence - b.sequence);
|
|
53
|
+
}
|
|
54
|
+
/** All summary nodes (unordered). */
|
|
55
|
+
allSummaries() {
|
|
56
|
+
return [...this.nodes.values()];
|
|
57
|
+
}
|
|
58
|
+
leaf(chunkId) {
|
|
59
|
+
return this.leaves.get(chunkId) ?? null;
|
|
60
|
+
}
|
|
61
|
+
summary(id) {
|
|
62
|
+
return this.nodes.get(id) ?? null;
|
|
63
|
+
}
|
|
64
|
+
/** Recall-pair tokens for a summary, or null if unknown. */
|
|
65
|
+
recallTokens(id) {
|
|
66
|
+
return this.nodes.get(id)?.recallTokens ?? null;
|
|
67
|
+
}
|
|
68
|
+
/** Immediate children of a summary node (leaves or sub-summaries). */
|
|
69
|
+
children(node) {
|
|
70
|
+
const out = [];
|
|
71
|
+
if (node.childrenAreLeaves) {
|
|
72
|
+
for (const cid of node.childIds) {
|
|
73
|
+
const leaf = this.leaves.get(cid);
|
|
74
|
+
if (leaf)
|
|
75
|
+
out.push(leaf);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
for (const sid of node.childIds) {
|
|
80
|
+
const sub = this.nodes.get(sid);
|
|
81
|
+
if (sub)
|
|
82
|
+
out.push(sub);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
/** All leaf chunk ids under a summary, in source order. */
|
|
88
|
+
leavesUnder(id) {
|
|
89
|
+
return this.nodes.get(id)?.leafChunkIds ?? [];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The L_level ancestor summary of a chunk, or null if not present. Matches
|
|
93
|
+
* `MutableFoldingState.ancestorAt` (walks the parentId chain from l1Id).
|
|
94
|
+
*/
|
|
95
|
+
ancestorAt(chunkId, level) {
|
|
96
|
+
if (level <= 0)
|
|
97
|
+
return null;
|
|
98
|
+
const leaf = this.leaves.get(chunkId);
|
|
99
|
+
if (!leaf || !leaf.l1Id)
|
|
100
|
+
return null;
|
|
101
|
+
let cur = this.nodes.get(leaf.l1Id);
|
|
102
|
+
while (cur && cur.level < level) {
|
|
103
|
+
if (!cur.parentId)
|
|
104
|
+
return null;
|
|
105
|
+
cur = this.nodes.get(cur.parentId);
|
|
106
|
+
}
|
|
107
|
+
return cur && cur.level === level ? cur : null;
|
|
108
|
+
}
|
|
109
|
+
/** Highest level k for which a summary covering this chunk exists (0 = none). */
|
|
110
|
+
maxLevel(chunkId) {
|
|
111
|
+
const leaf = this.leaves.get(chunkId);
|
|
112
|
+
if (!leaf || !leaf.l1Id)
|
|
113
|
+
return 0;
|
|
114
|
+
let cur = this.nodes.get(leaf.l1Id);
|
|
115
|
+
let max = 0;
|
|
116
|
+
while (cur) {
|
|
117
|
+
max = cur.level;
|
|
118
|
+
if (!cur.parentId)
|
|
119
|
+
break;
|
|
120
|
+
cur = this.nodes.get(cur.parentId);
|
|
121
|
+
}
|
|
122
|
+
return max;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Forest roots over all chunks: top-level summaries (no parent present in the
|
|
126
|
+
* map) plus any leaf not covered by an L1. Each leaf belongs to exactly one
|
|
127
|
+
* root's subtree. Deterministically ordered by source sequence.
|
|
128
|
+
*/
|
|
129
|
+
roots() {
|
|
130
|
+
if (this.rootCache)
|
|
131
|
+
return this.rootCache;
|
|
132
|
+
const out = [];
|
|
133
|
+
const covered = new Set();
|
|
134
|
+
for (const node of this.nodes.values()) {
|
|
135
|
+
const parent = node.parentId ? this.nodes.get(node.parentId) : undefined;
|
|
136
|
+
if (parent)
|
|
137
|
+
continue; // has a real parent → not a root
|
|
138
|
+
out.push(node);
|
|
139
|
+
for (const lid of node.leafChunkIds)
|
|
140
|
+
covered.add(lid);
|
|
141
|
+
}
|
|
142
|
+
for (const leaf of this.leaves.values()) {
|
|
143
|
+
if (!covered.has(leaf.chunkId))
|
|
144
|
+
out.push(leaf);
|
|
145
|
+
}
|
|
146
|
+
out.sort((a, b) => sequenceOf(a) - sequenceOf(b));
|
|
147
|
+
this.rootCache = out;
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
150
|
+
// ---- internals ----
|
|
151
|
+
buildNode(s) {
|
|
152
|
+
const leafChunkIds = this.collectLeafIds(s);
|
|
153
|
+
let firstSequence = Infinity;
|
|
154
|
+
let lastSequence = -Infinity;
|
|
155
|
+
for (const id of leafChunkIds) {
|
|
156
|
+
const seq = this.leafSeq.get(id);
|
|
157
|
+
if (seq === undefined)
|
|
158
|
+
continue;
|
|
159
|
+
if (seq < firstSequence)
|
|
160
|
+
firstSequence = seq;
|
|
161
|
+
if (seq > lastSequence)
|
|
162
|
+
lastSequence = seq;
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
kind: 'summary',
|
|
166
|
+
id: s.id,
|
|
167
|
+
level: s.level,
|
|
168
|
+
recallTokens: this.recallPairTokens.get(s.id) ?? s.tokens,
|
|
169
|
+
childIds: [...s.sourceIds],
|
|
170
|
+
childrenAreLeaves: s.sourceLevel === 0,
|
|
171
|
+
leafChunkIds,
|
|
172
|
+
firstSequence: firstSequence === Infinity ? -1 : firstSequence,
|
|
173
|
+
lastSequence: lastSequence === -Infinity ? -1 : lastSequence,
|
|
174
|
+
sourceRange: s.sourceRange,
|
|
175
|
+
parentId: getSummaryParentId(s),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/** Walk down to leaf chunk ids; sourceLevel 0 => sourceIds are leaves.
|
|
179
|
+
* Deduplicates leaves and guards against revisiting a summary, so a chunk
|
|
180
|
+
* reachable via multiple branches is counted once (real chronicles can have
|
|
181
|
+
* such overlap; double-counting breaks range/contiguity and value math). */
|
|
182
|
+
collectLeafIds(summary) {
|
|
183
|
+
const out = [];
|
|
184
|
+
const seenLeaves = new Set();
|
|
185
|
+
const seenSummaries = new Set();
|
|
186
|
+
const visit = (s) => {
|
|
187
|
+
if (seenSummaries.has(s.id))
|
|
188
|
+
return;
|
|
189
|
+
seenSummaries.add(s.id);
|
|
190
|
+
if (s.sourceLevel === 0) {
|
|
191
|
+
for (const mid of s.sourceIds) {
|
|
192
|
+
if (!seenLeaves.has(mid)) {
|
|
193
|
+
seenLeaves.add(mid);
|
|
194
|
+
out.push(mid);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
for (const sid of s.sourceIds) {
|
|
200
|
+
const child = this.summaries.get(sid);
|
|
201
|
+
if (child)
|
|
202
|
+
visit(child);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
visit(summary);
|
|
207
|
+
out.sort((a, b) => (this.leafSeq.get(a) ?? 0) - (this.leafSeq.get(b) ?? 0));
|
|
208
|
+
return out;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function sequenceOf(n) {
|
|
212
|
+
return n.kind === 'leaf' ? n.sequence : n.firstSequence;
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=summary-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary-tree.js","sourceRoot":"","sources":["../../../src/adaptive/summary-tree.ts"],"names":[],"mappings":"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"}
|