@animalabs/context-manager 0.4.0 → 0.5.0

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.
Files changed (128) hide show
  1. package/dist/src/adaptive/chunker.d.ts +70 -0
  2. package/dist/src/adaptive/chunker.d.ts.map +1 -0
  3. package/dist/src/adaptive/chunker.js +233 -0
  4. package/dist/src/adaptive/chunker.js.map +1 -0
  5. package/dist/src/adaptive/folding-strategy.d.ts +118 -0
  6. package/dist/src/adaptive/folding-strategy.d.ts.map +1 -0
  7. package/dist/src/adaptive/folding-strategy.js +12 -0
  8. package/dist/src/adaptive/folding-strategy.js.map +1 -0
  9. package/dist/src/adaptive/index.d.ts +17 -0
  10. package/dist/src/adaptive/index.d.ts.map +1 -0
  11. package/dist/src/adaptive/index.js +23 -0
  12. package/dist/src/adaptive/index.js.map +1 -0
  13. package/dist/src/adaptive/picker.d.ts +103 -0
  14. package/dist/src/adaptive/picker.d.ts.map +1 -0
  15. package/dist/src/adaptive/picker.js +357 -0
  16. package/dist/src/adaptive/picker.js.map +1 -0
  17. package/dist/src/adaptive/render.d.ts +39 -0
  18. package/dist/src/adaptive/render.d.ts.map +1 -0
  19. package/dist/src/adaptive/render.js +104 -0
  20. package/dist/src/adaptive/render.js.map +1 -0
  21. package/dist/src/adaptive/strategies/flat-profile.d.ts +19 -0
  22. package/dist/src/adaptive/strategies/flat-profile.d.ts.map +1 -0
  23. package/dist/src/adaptive/strategies/flat-profile.js +86 -0
  24. package/dist/src/adaptive/strategies/flat-profile.js.map +1 -0
  25. package/dist/src/adaptive/strategies/oldest-first.d.ts +19 -0
  26. package/dist/src/adaptive/strategies/oldest-first.d.ts.map +1 -0
  27. package/dist/src/adaptive/strategies/oldest-first.js +39 -0
  28. package/dist/src/adaptive/strategies/oldest-first.js.map +1 -0
  29. package/dist/src/context-manager.d.ts +5 -0
  30. package/dist/src/context-manager.d.ts.map +1 -1
  31. package/dist/src/context-manager.js +22 -0
  32. package/dist/src/context-manager.js.map +1 -1
  33. package/dist/src/index.d.ts +1 -1
  34. package/dist/src/index.d.ts.map +1 -1
  35. package/dist/src/index.js.map +1 -1
  36. package/dist/src/message-store.d.ts +36 -1
  37. package/dist/src/message-store.d.ts.map +1 -1
  38. package/dist/src/message-store.js +134 -8
  39. package/dist/src/message-store.js.map +1 -1
  40. package/dist/src/strategies/autobiographical.d.ts +217 -2
  41. package/dist/src/strategies/autobiographical.d.ts.map +1 -1
  42. package/dist/src/strategies/autobiographical.js +1479 -37
  43. package/dist/src/strategies/autobiographical.js.map +1 -1
  44. package/dist/src/strategies/index.d.ts +1 -1
  45. package/dist/src/strategies/index.d.ts.map +1 -1
  46. package/dist/src/strategies/index.js.map +1 -1
  47. package/dist/src/types/message.d.ts +38 -0
  48. package/dist/src/types/message.d.ts.map +1 -1
  49. package/dist/src/types/strategy.d.ts +94 -10
  50. package/dist/src/types/strategy.d.ts.map +1 -1
  51. package/dist/src/types/strategy.js +7 -0
  52. package/dist/src/types/strategy.js.map +1 -1
  53. package/dist/test/adaptive/branching.test.d.ts +20 -0
  54. package/dist/test/adaptive/branching.test.d.ts.map +1 -0
  55. package/dist/test/adaptive/branching.test.js +176 -0
  56. package/dist/test/adaptive/branching.test.js.map +1 -0
  57. package/dist/test/adaptive/chunker.test.d.ts +2 -0
  58. package/dist/test/adaptive/chunker.test.d.ts.map +1 -0
  59. package/dist/test/adaptive/chunker.test.js +120 -0
  60. package/dist/test/adaptive/chunker.test.js.map +1 -0
  61. package/dist/test/adaptive/deep-levels.test.d.ts +10 -0
  62. package/dist/test/adaptive/deep-levels.test.d.ts.map +1 -0
  63. package/dist/test/adaptive/deep-levels.test.js +167 -0
  64. package/dist/test/adaptive/deep-levels.test.js.map +1 -0
  65. package/dist/test/adaptive/doc-plus-chat.test.d.ts +10 -0
  66. package/dist/test/adaptive/doc-plus-chat.test.d.ts.map +1 -0
  67. package/dist/test/adaptive/doc-plus-chat.test.js +194 -0
  68. package/dist/test/adaptive/doc-plus-chat.test.js.map +1 -0
  69. package/dist/test/adaptive/hard-fail.test.d.ts +9 -0
  70. package/dist/test/adaptive/hard-fail.test.d.ts.map +1 -0
  71. package/dist/test/adaptive/hard-fail.test.js +154 -0
  72. package/dist/test/adaptive/hard-fail.test.js.map +1 -0
  73. package/dist/test/adaptive/harness.d.ts +109 -0
  74. package/dist/test/adaptive/harness.d.ts.map +1 -0
  75. package/dist/test/adaptive/harness.js +263 -0
  76. package/dist/test/adaptive/harness.js.map +1 -0
  77. package/dist/test/adaptive/ingestion.test.d.ts +13 -0
  78. package/dist/test/adaptive/ingestion.test.d.ts.map +1 -0
  79. package/dist/test/adaptive/ingestion.test.js +306 -0
  80. package/dist/test/adaptive/ingestion.test.js.map +1 -0
  81. package/dist/test/adaptive/integration.test.d.ts +12 -0
  82. package/dist/test/adaptive/integration.test.d.ts.map +1 -0
  83. package/dist/test/adaptive/integration.test.js +247 -0
  84. package/dist/test/adaptive/integration.test.js.map +1 -0
  85. package/dist/test/adaptive/long-chronicle.test.d.ts +13 -0
  86. package/dist/test/adaptive/long-chronicle.test.d.ts.map +1 -0
  87. package/dist/test/adaptive/long-chronicle.test.js +186 -0
  88. package/dist/test/adaptive/long-chronicle.test.js.map +1 -0
  89. package/dist/test/adaptive/persistence.test.d.ts +11 -0
  90. package/dist/test/adaptive/persistence.test.d.ts.map +1 -0
  91. package/dist/test/adaptive/persistence.test.js +200 -0
  92. package/dist/test/adaptive/persistence.test.js.map +1 -0
  93. package/dist/test/adaptive/picker.test.d.ts +2 -0
  94. package/dist/test/adaptive/picker.test.d.ts.map +1 -0
  95. package/dist/test/adaptive/picker.test.js +333 -0
  96. package/dist/test/adaptive/picker.test.js.map +1 -0
  97. package/dist/test/adaptive/render.test.d.ts +2 -0
  98. package/dist/test/adaptive/render.test.d.ts.map +1 -0
  99. package/dist/test/adaptive/render.test.js +109 -0
  100. package/dist/test/adaptive/render.test.js.map +1 -0
  101. package/dist/test/adaptive/shard-immutability.test.d.ts +14 -0
  102. package/dist/test/adaptive/shard-immutability.test.d.ts.map +1 -0
  103. package/dist/test/adaptive/shard-immutability.test.js +184 -0
  104. package/dist/test/adaptive/shard-immutability.test.js.map +1 -0
  105. package/dist/test/adaptive/strategy-integration.test.d.ts +9 -0
  106. package/dist/test/adaptive/strategy-integration.test.d.ts.map +1 -0
  107. package/dist/test/adaptive/strategy-integration.test.js +293 -0
  108. package/dist/test/adaptive/strategy-integration.test.js.map +1 -0
  109. package/dist/test/message-store-sequence.test.d.ts +25 -0
  110. package/dist/test/message-store-sequence.test.d.ts.map +1 -0
  111. package/dist/test/message-store-sequence.test.js +157 -0
  112. package/dist/test/message-store-sequence.test.js.map +1 -0
  113. package/dist/tsconfig.tsbuildinfo +1 -1
  114. package/package.json +1 -1
  115. package/src/adaptive/chunker.ts +323 -0
  116. package/src/adaptive/folding-strategy.ts +129 -0
  117. package/src/adaptive/index.ts +51 -0
  118. package/src/adaptive/picker.ts +442 -0
  119. package/src/adaptive/render.ts +115 -0
  120. package/src/adaptive/strategies/flat-profile.ts +96 -0
  121. package/src/adaptive/strategies/oldest-first.ts +48 -0
  122. package/src/context-manager.ts +32 -0
  123. package/src/index.ts +1 -1
  124. package/src/message-store.ts +147 -8
  125. package/src/strategies/autobiographical.ts +1586 -38
  126. package/src/strategies/index.ts +1 -1
  127. package/src/types/message.ts +43 -0
  128. package/src/types/strategy.ts +109 -10
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Tests that adaptive-resolution state (currentResolution + lockedByAgent)
3
+ * survives a close-and-reopen of the ContextManager.
4
+ *
5
+ * Without these slots persisted, a process restart would re-run the picker
6
+ * from scratch on first compile, almost certainly producing a different
7
+ * fold pattern → full KV invalidation. The chronicle slots ensure the
8
+ * picker resumes where it left off.
9
+ */
10
+ import { describe, it, before, after, beforeEach } from 'node:test';
11
+ import assert from 'node:assert/strict';
12
+ import { rmSync, existsSync } from 'node:fs';
13
+ import { ContextManager, AutobiographicalStrategy } from '../../src/index.js';
14
+ const TEST_STORE_PATH = './test-adaptive-persistence-store';
15
+ function cleanup() {
16
+ if (existsSync(TEST_STORE_PATH)) {
17
+ rmSync(TEST_STORE_PATH, { recursive: true, force: true });
18
+ }
19
+ }
20
+ function makeMockMembrane() {
21
+ let callCount = 0;
22
+ return {
23
+ complete: async () => {
24
+ callCount++;
25
+ return {
26
+ content: [{ type: 'text', text: `[mock summary #${callCount}]` }],
27
+ };
28
+ },
29
+ get callCount() {
30
+ return callCount;
31
+ },
32
+ };
33
+ }
34
+ describe('AutobiographicalStrategy — adaptive state persistence', () => {
35
+ before(() => cleanup());
36
+ after(() => cleanup());
37
+ beforeEach(() => cleanup());
38
+ it('resolutions survive close + reopen', async () => {
39
+ // Phase 1: open, ingest, compile under pressure, capture resolutions
40
+ const mock1 = makeMockMembrane();
41
+ const strategy1 = new AutobiographicalStrategy({
42
+ adaptiveResolution: true,
43
+ targetChunkTokens: 100,
44
+ recentWindowTokens: 200,
45
+ });
46
+ const manager1 = await ContextManager.open({
47
+ path: TEST_STORE_PATH,
48
+ strategy: strategy1,
49
+ membrane: mock1,
50
+ });
51
+ for (let i = 0; i < 40; i++) {
52
+ manager1.addMessage('User', [{ type: 'text', text: `Turn ${i}. ` + 'word '.repeat(60) }]);
53
+ }
54
+ while (!manager1.isReady()) {
55
+ await manager1.tick();
56
+ }
57
+ // Force folding with a tight budget
58
+ await manager1.compile({ maxTokens: 1500, reserveForResponse: 200 });
59
+ const phase1Resolutions = new Map(strategy1.resolutions);
60
+ // Debug: log what we have
61
+ if (phase1Resolutions.size === 0) {
62
+ const stats = strategy1.getStats?.() ?? {};
63
+ console.error('phase 1 resolutions empty; stats:', stats);
64
+ }
65
+ assert.ok(phase1Resolutions.size > 0, `phase 1 should have folded at least some messages; got ${phase1Resolutions.size}`);
66
+ manager1.close();
67
+ // Phase 2: reopen with a fresh strategy instance, verify resolutions restored
68
+ const mock2 = makeMockMembrane();
69
+ const strategy2 = new AutobiographicalStrategy({
70
+ adaptiveResolution: true,
71
+ targetChunkTokens: 100,
72
+ recentWindowTokens: 200,
73
+ });
74
+ const manager2 = await ContextManager.open({
75
+ path: TEST_STORE_PATH,
76
+ strategy: strategy2,
77
+ membrane: mock2,
78
+ });
79
+ // Without compiling, the strategy.resolutions should already be populated from chronicle
80
+ const phase2Resolutions = new Map(strategy2.resolutions);
81
+ assert.equal(phase2Resolutions.size, phase1Resolutions.size, `phase 2 should have ${phase1Resolutions.size} resolutions; got ${phase2Resolutions.size}`);
82
+ for (const [id, level] of phase1Resolutions) {
83
+ assert.equal(phase2Resolutions.get(id), level, `message ${id}: phase 1 had L${level}, phase 2 has L${phase2Resolutions.get(id)}`);
84
+ }
85
+ manager2.close();
86
+ });
87
+ it('locks survive close + reopen', async () => {
88
+ const mock1 = makeMockMembrane();
89
+ const strategy1 = new AutobiographicalStrategy({
90
+ adaptiveResolution: true,
91
+ targetChunkTokens: 100,
92
+ recentWindowTokens: 200,
93
+ });
94
+ const manager1 = await ContextManager.open({
95
+ path: TEST_STORE_PATH,
96
+ strategy: strategy1,
97
+ membrane: mock1,
98
+ });
99
+ const ids = [];
100
+ for (let i = 0; i < 8; i++) {
101
+ ids.push(manager1.addMessage('User', [{ type: 'text', text: `Turn ${i}` }]));
102
+ }
103
+ // Lock a couple of messages
104
+ strategy1.lockChunk(ids[2]);
105
+ strategy1.lockChunk(ids[5]);
106
+ manager1.close();
107
+ // Reopen
108
+ const mock2 = makeMockMembrane();
109
+ const strategy2 = new AutobiographicalStrategy({
110
+ adaptiveResolution: true,
111
+ targetChunkTokens: 100,
112
+ recentWindowTokens: 200,
113
+ });
114
+ const manager2 = await ContextManager.open({
115
+ path: TEST_STORE_PATH,
116
+ strategy: strategy2,
117
+ membrane: mock2,
118
+ });
119
+ const lockedAfterReopen = strategy2.locked;
120
+ assert.equal(lockedAfterReopen.size, 2);
121
+ assert.ok(lockedAfterReopen.has(ids[2]), `${ids[2]} should be locked after reopen`);
122
+ assert.ok(lockedAfterReopen.has(ids[5]), `${ids[5]} should be locked after reopen`);
123
+ manager2.close();
124
+ });
125
+ it('unlocking persists too', async () => {
126
+ const mock1 = makeMockMembrane();
127
+ const strategy1 = new AutobiographicalStrategy({
128
+ adaptiveResolution: true,
129
+ });
130
+ const manager1 = await ContextManager.open({
131
+ path: TEST_STORE_PATH,
132
+ strategy: strategy1,
133
+ membrane: mock1,
134
+ });
135
+ const id = manager1.addMessage('User', [{ type: 'text', text: 'msg' }]);
136
+ strategy1.lockChunk(id);
137
+ strategy1.unlockChunk(id);
138
+ manager1.close();
139
+ const strategy2 = new AutobiographicalStrategy({ adaptiveResolution: true });
140
+ const manager2 = await ContextManager.open({
141
+ path: TEST_STORE_PATH,
142
+ strategy: strategy2,
143
+ membrane: makeMockMembrane(),
144
+ });
145
+ const lockedAfter = strategy2.locked;
146
+ assert.equal(lockedAfter.size, 0, 'after lock+unlock+reopen, no locks should remain');
147
+ manager2.close();
148
+ });
149
+ it('compile after reopen produces same fold pattern (no thrashing)', async () => {
150
+ // Phase 1: drive compression and folding
151
+ const mock1 = makeMockMembrane();
152
+ const strategy1 = new AutobiographicalStrategy({
153
+ adaptiveResolution: true,
154
+ targetChunkTokens: 100,
155
+ recentWindowTokens: 200,
156
+ });
157
+ const manager1 = await ContextManager.open({
158
+ path: TEST_STORE_PATH,
159
+ strategy: strategy1,
160
+ membrane: mock1,
161
+ });
162
+ for (let i = 0; i < 18; i++) {
163
+ manager1.addMessage('User', [{ type: 'text', text: `Turn ${i}. ` + 'word '.repeat(40) }]);
164
+ }
165
+ while (!manager1.isReady()) {
166
+ await manager1.tick();
167
+ }
168
+ const compileA = await manager1.compile({ maxTokens: 3000, reserveForResponse: 200 });
169
+ const resolutionsA = new Map(strategy1.resolutions);
170
+ manager1.close();
171
+ // Phase 2: reopen, compile with same budget
172
+ const mock2 = makeMockMembrane();
173
+ const strategy2 = new AutobiographicalStrategy({
174
+ adaptiveResolution: true,
175
+ targetChunkTokens: 100,
176
+ recentWindowTokens: 200,
177
+ });
178
+ const manager2 = await ContextManager.open({
179
+ path: TEST_STORE_PATH,
180
+ strategy: strategy2,
181
+ membrane: mock2,
182
+ });
183
+ while (!manager2.isReady()) {
184
+ await manager2.tick();
185
+ }
186
+ const compileB = await manager2.compile({ maxTokens: 3000, reserveForResponse: 200 });
187
+ const resolutionsB = new Map(strategy2.resolutions);
188
+ // Resolutions should be identical — no thrashing across the reopen.
189
+ for (const [id, levelA] of resolutionsA) {
190
+ const levelB = resolutionsB.get(id);
191
+ assert.equal(levelB, levelA, `after reopen, message ${id} should still be at L${levelA}, got L${levelB}`);
192
+ }
193
+ // Compile output should also be substantially equivalent — same number of
194
+ // entries with same participants in same order. (Exact text may differ
195
+ // because the mock LLM uses an incrementing callCount.)
196
+ assert.equal(compileB.messages.length, compileA.messages.length, `compile entry count differs after reopen (was ${compileA.messages.length}, now ${compileB.messages.length})`);
197
+ manager2.close();
198
+ });
199
+ });
200
+ //# sourceMappingURL=persistence.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.test.js","sourceRoot":"","sources":["../../../test/adaptive/persistence.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=picker.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.test.d.ts","sourceRoot":"","sources":["../../../test/adaptive/picker.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,333 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { Picker } from '../../src/adaptive/picker.js';
4
+ import { FlatProfileStrategy } from '../../src/adaptive/strategies/flat-profile.js';
5
+ import { OldestFirstStrategy } from '../../src/adaptive/strategies/oldest-first.js';
6
+ import { buildChronicleWithChain, MockChronicle } from './harness.js';
7
+ const BUDGET = (totalBudget, slack = 0.1) => ({
8
+ totalBudget,
9
+ targetBudget: totalBudget * (1 - slack),
10
+ slack,
11
+ });
12
+ test('picker: under budget — no folds', () => {
13
+ const chronicle = buildChronicleWithChain({
14
+ chunkCount: 12,
15
+ tokensPerChunk: 100,
16
+ });
17
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 300 });
18
+ const picker = new Picker(new FlatProfileStrategy());
19
+ const result = picker.run({
20
+ chunks: chronicle.chunks,
21
+ summaries: chronicle.summaries,
22
+ recallPairTokens: chronicle.recallPairTokens,
23
+ ...tailInfo,
24
+ }, BUDGET(100_000));
25
+ assert.equal(result.applied.length, 0);
26
+ assert.equal(result.iterations, 0);
27
+ assert.equal(result.budgetMet, true);
28
+ });
29
+ test('picker: over budget — flat-profile raises oldest group at L0', () => {
30
+ // 12 chunks × 100 tokens = 1200 raw. mergeThreshold=6 → 2 L1 groups (no L2 produced).
31
+ // With budget 700 / target 630, two L1 folds bring us to ~600 → budget met.
32
+ const chronicle = buildChronicleWithChain({
33
+ chunkCount: 12,
34
+ tokensPerChunk: 100,
35
+ mergeThreshold: 6,
36
+ recallPairTokens: 200,
37
+ });
38
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 200 });
39
+ const picker = new Picker(new FlatProfileStrategy());
40
+ const result = picker.run({
41
+ chunks: chronicle.chunks,
42
+ summaries: chronicle.summaries,
43
+ recallPairTokens: chronicle.recallPairTokens,
44
+ ...tailInfo,
45
+ }, BUDGET(700));
46
+ assert.ok(result.applied.length > 0, 'should have applied at least one fold');
47
+ for (const op of result.applied) {
48
+ assert.equal(op.kind, 'raise');
49
+ }
50
+ assert.equal(result.budgetMet, true);
51
+ });
52
+ test('picker: over budget without L2 available — emits produce op', () => {
53
+ // 12 chunks × 100, 2 L1 groups, no L2. Budget 400 forces deeper folding.
54
+ const chronicle = buildChronicleWithChain({
55
+ chunkCount: 12,
56
+ tokensPerChunk: 100,
57
+ mergeThreshold: 6,
58
+ recallPairTokens: 200,
59
+ });
60
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 200 });
61
+ const picker = new Picker(new FlatProfileStrategy());
62
+ const result = picker.run({
63
+ chunks: chronicle.chunks,
64
+ summaries: chronicle.summaries,
65
+ recallPairTokens: chronicle.recallPairTokens,
66
+ ...tailInfo,
67
+ }, BUDGET(400));
68
+ // Should have applied L1 folds AND requested L2 production.
69
+ assert.ok(result.applied.length > 0);
70
+ assert.ok(result.produced.length > 0, 'should have emitted produce op for L2');
71
+ const produceOp = result.produced[0];
72
+ if (produceOp.kind === 'produce') {
73
+ assert.equal(produceOp.level, 2);
74
+ }
75
+ });
76
+ test('picker: group-fold semantics — raising one chunk to L1 raises all siblings under same L1', () => {
77
+ const chronicle = buildChronicleWithChain({
78
+ chunkCount: 12,
79
+ tokensPerChunk: 100,
80
+ mergeThreshold: 6,
81
+ recallPairTokens: 100,
82
+ });
83
+ // Force pressure such that exactly one L1 group is folded.
84
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
85
+ const picker = new Picker(new FlatProfileStrategy());
86
+ const result = picker.run({
87
+ chunks: chronicle.chunks,
88
+ summaries: chronicle.summaries,
89
+ recallPairTokens: chronicle.recallPairTokens,
90
+ ...tailInfo,
91
+ }, BUDGET(1000));
92
+ // After folding, count how many chunks at L1 vs L0.
93
+ const l1Chunks = [];
94
+ for (const [id, level] of result.finalResolutions) {
95
+ if (level === 1)
96
+ l1Chunks.push(id);
97
+ }
98
+ // L1 chunks should come in multiples of 6 (one group at a time).
99
+ assert.equal(l1Chunks.length % 6, 0, `L1 chunk count ${l1Chunks.length} should be multiple of 6`);
100
+ // And they should be contiguous from the oldest.
101
+ l1Chunks.sort();
102
+ for (let i = 0; i < l1Chunks.length; i++) {
103
+ assert.equal(l1Chunks[i], `c-${i.toString().padStart(4, '0')}`);
104
+ }
105
+ });
106
+ test('picker: oldest-first strategy raises chronologically', () => {
107
+ const chronicle = buildChronicleWithChain({
108
+ chunkCount: 12,
109
+ tokensPerChunk: 100,
110
+ mergeThreshold: 6,
111
+ recallPairTokens: 100,
112
+ });
113
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
114
+ const picker = new Picker(new OldestFirstStrategy());
115
+ const result = picker.run({
116
+ chunks: chronicle.chunks,
117
+ summaries: chronicle.summaries,
118
+ recallPairTokens: chronicle.recallPairTokens,
119
+ ...tailInfo,
120
+ }, BUDGET(900));
121
+ // First raise should target the oldest chunks (c-0000…c-0005)
122
+ if (result.applied.length > 0) {
123
+ const firstOp = result.applied[0];
124
+ assert.equal(firstOp.kind, 'raise');
125
+ // The groupRoot is an L1, and its source range should start at c-0000.
126
+ if (firstOp.kind === 'raise') {
127
+ const summary = chronicle.summaries.get(firstOp.groupRoot);
128
+ assert.equal(summary.sourceRange.first, 'c-0000');
129
+ }
130
+ }
131
+ });
132
+ test('picker: monotonicity — re-running with same state does not lower anything', () => {
133
+ const chronicle = buildChronicleWithChain({
134
+ chunkCount: 18,
135
+ tokensPerChunk: 100,
136
+ mergeThreshold: 6,
137
+ recallPairTokens: 100,
138
+ });
139
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
140
+ const picker = new Picker(new FlatProfileStrategy());
141
+ // First run
142
+ const r1 = picker.run({
143
+ chunks: chronicle.chunks,
144
+ summaries: chronicle.summaries,
145
+ recallPairTokens: chronicle.recallPairTokens,
146
+ ...tailInfo,
147
+ }, BUDGET(800));
148
+ chronicle.applyResolutions(r1.finalResolutions);
149
+ // Second run with same inputs — should not change anything.
150
+ const r2 = picker.run({
151
+ chunks: chronicle.chunks,
152
+ summaries: chronicle.summaries,
153
+ recallPairTokens: chronicle.recallPairTokens,
154
+ ...tailInfo,
155
+ }, BUDGET(800));
156
+ assert.equal(r2.applied.length, 0, 'second run with no pressure change should not apply folds');
157
+ // All chunks' resolutions stable
158
+ for (const c of chronicle.chunks) {
159
+ const r1Val = r1.finalResolutions.get(c.id);
160
+ const r2Val = r2.finalResolutions.get(c.id);
161
+ assert.equal(r2Val, r1Val);
162
+ }
163
+ });
164
+ test('picker: locked chunks survive partial group fold', () => {
165
+ const chronicle = buildChronicleWithChain({
166
+ chunkCount: 12,
167
+ tokensPerChunk: 100,
168
+ mergeThreshold: 6,
169
+ recallPairTokens: 100,
170
+ });
171
+ // Lock chunk c-0003 (in the first L1 group).
172
+ chronicle.chunks[3].lockedByAgent = true;
173
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
174
+ const picker = new Picker(new FlatProfileStrategy());
175
+ const result = picker.run({
176
+ chunks: chronicle.chunks,
177
+ summaries: chronicle.summaries,
178
+ recallPairTokens: chronicle.recallPairTokens,
179
+ ...tailInfo,
180
+ }, BUDGET(900));
181
+ // After folding the first L1 group, c-0003 should still be at L0.
182
+ // Other chunks in that group should be at L1.
183
+ if (result.finalResolutions.get('c-0000') === 1) {
184
+ assert.equal(result.finalResolutions.get('c-0003'), 0, 'locked chunk should not be raised');
185
+ assert.equal(result.finalResolutions.get('c-0001'), 1);
186
+ assert.equal(result.finalResolutions.get('c-0002'), 1);
187
+ assert.equal(result.finalResolutions.get('c-0004'), 1);
188
+ assert.equal(result.finalResolutions.get('c-0005'), 1);
189
+ }
190
+ });
191
+ test('picker: pinned chunks always render raw, never folded', () => {
192
+ const chronicle = buildChronicleWithChain({
193
+ chunkCount: 12,
194
+ tokensPerChunk: 100,
195
+ mergeThreshold: 6,
196
+ recallPairTokens: 100,
197
+ });
198
+ chronicle.chunks[5].pinned = true; // Pin chunk in first L1 group
199
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
200
+ const picker = new Picker(new FlatProfileStrategy());
201
+ const result = picker.run({
202
+ chunks: chronicle.chunks,
203
+ summaries: chronicle.summaries,
204
+ recallPairTokens: chronicle.recallPairTokens,
205
+ ...tailInfo,
206
+ }, BUDGET(900));
207
+ // Pinned chunk is not in foldableMiddle, so it isn't raised.
208
+ assert.equal(result.finalResolutions.get('c-0005'), 0);
209
+ });
210
+ test('picker: deep folding cascades through levels (L1 → L2 → L3 → …)', () => {
211
+ // Many chunks → deep tree. With aggressive budget, picker should fold to higher levels.
212
+ const chronicle = buildChronicleWithChain({
213
+ chunkCount: 36, // 36 / 6 = 6 L1s; 6 L1s = 1 L2; need more to test L2 → L3
214
+ tokensPerChunk: 100,
215
+ mergeThreshold: 6,
216
+ recallPairTokens: 50,
217
+ });
218
+ // 36 chunks × 100 tokens = 3600. With budget 200 and recallPair 50, force deep folding.
219
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
220
+ const picker = new Picker(new FlatProfileStrategy());
221
+ const result = picker.run({
222
+ chunks: chronicle.chunks,
223
+ summaries: chronicle.summaries,
224
+ recallPairTokens: chronicle.recallPairTokens,
225
+ ...tailInfo,
226
+ }, BUDGET(300));
227
+ assert.equal(result.budgetMet, true);
228
+ // Should have raised to at least L1 for the middle, possibly higher.
229
+ const maxLevel = Math.max(...Array.from(result.finalResolutions.values()));
230
+ assert.ok(maxLevel >= 1, `expected max level >= 1, got ${maxLevel}`);
231
+ });
232
+ test('picker: produce op emitted when L_{k+1} missing', () => {
233
+ // Build chronicle WITHOUT producing the full chain — only L1s.
234
+ const chronicle = new MockChronicle({ mergeThreshold: 6, recallPairTokens: 50 });
235
+ for (let i = 0; i < 18; i++) {
236
+ chronicle.addChunk({ id: `c-${i.toString().padStart(4, '0')}`, rawTokens: 100 });
237
+ }
238
+ // Only L1 chain — no L2 yet.
239
+ for (let i = 0; i < 18; i += 6) {
240
+ chronicle.produceL1(chronicle.chunks.slice(i, i + 6).map((c) => c.id));
241
+ }
242
+ // Manually raise all chunks to L1 to simulate prior fold state.
243
+ for (const c of chronicle.chunks)
244
+ c.currentResolution = 1;
245
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
246
+ const picker = new Picker(new FlatProfileStrategy());
247
+ const result = picker.run({
248
+ chunks: chronicle.chunks,
249
+ summaries: chronicle.summaries,
250
+ recallPairTokens: chronicle.recallPairTokens,
251
+ ...tailInfo,
252
+ }, BUDGET(120));
253
+ // The picker should ask for an L2 to be produced.
254
+ assert.ok(result.produced.length > 0, 'should have requested L2 production');
255
+ const produceOp = result.produced[0];
256
+ assert.equal(produceOp.kind, 'produce');
257
+ if (produceOp.kind === 'produce') {
258
+ assert.equal(produceOp.level, 2);
259
+ }
260
+ });
261
+ test('picker: head and tail chunks are never folded', () => {
262
+ const chronicle = buildChronicleWithChain({
263
+ chunkCount: 18,
264
+ tokensPerChunk: 100,
265
+ mergeThreshold: 6,
266
+ recallPairTokens: 100,
267
+ });
268
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 200, tailTokens: 200 });
269
+ const picker = new Picker(new FlatProfileStrategy());
270
+ const result = picker.run({
271
+ chunks: chronicle.chunks,
272
+ summaries: chronicle.summaries,
273
+ recallPairTokens: chronicle.recallPairTokens,
274
+ ...tailInfo,
275
+ }, BUDGET(500));
276
+ // Head chunks (first 2 = 200 tokens) and tail chunks (last 2 = 200 tokens) stay at L0.
277
+ for (const id of tailInfo.headChunkIds) {
278
+ assert.equal(result.finalResolutions.get(id), 0, `head chunk ${id} should remain L0`);
279
+ }
280
+ for (const id of tailInfo.tailChunkIds) {
281
+ assert.equal(result.finalResolutions.get(id), 0, `tail chunk ${id} should remain L0`);
282
+ }
283
+ });
284
+ test('picker: 500K-token doc scenario — folds dramatically without exhausting', () => {
285
+ // Simulate a single 500K-token doc as 125 shards of ~4K tokens each.
286
+ const SHARD_TOKENS = 4000;
287
+ const SHARD_COUNT = 125;
288
+ const RECALL_PAIR_TOKENS = 200;
289
+ const chronicle = buildChronicleWithChain({
290
+ chunkCount: SHARD_COUNT,
291
+ tokensPerChunk: SHARD_TOKENS,
292
+ mergeThreshold: 6,
293
+ recallPairTokens: RECALL_PAIR_TOKENS,
294
+ });
295
+ // Assign all shards the same bodyGroupId.
296
+ for (const c of chronicle.chunks)
297
+ c.bodyGroupId = 'doc-1';
298
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 0 });
299
+ // Budget 100K — doc can't fit at L0 (500K) or even at L1 (~125 × 200 = 25K, fits!).
300
+ // Try budget 30K — at L1 it's tight, picker should fold further.
301
+ const picker = new Picker(new FlatProfileStrategy());
302
+ const result = picker.run({
303
+ chunks: chronicle.chunks,
304
+ summaries: chronicle.summaries,
305
+ recallPairTokens: chronicle.recallPairTokens,
306
+ ...tailInfo,
307
+ }, BUDGET(30_000));
308
+ // Picker should converge — either budget met or further produce requests pending.
309
+ assert.ok(result.budgetMet || result.produced.length > 0, `picker should converge: budgetMet=${result.budgetMet}, produced=${result.produced.length}`);
310
+ // Most shards should not be at L0 anymore.
311
+ const l0Count = Array.from(result.finalResolutions.values()).filter((v) => v === 0).length;
312
+ assert.ok(l0Count < SHARD_COUNT / 2, `expected most shards folded, but ${l0Count} of ${SHARD_COUNT} still at L0`);
313
+ });
314
+ test('picker: hits soft target with slack-bounded room', () => {
315
+ const chronicle = buildChronicleWithChain({
316
+ chunkCount: 30,
317
+ tokensPerChunk: 100,
318
+ mergeThreshold: 6,
319
+ recallPairTokens: 100,
320
+ });
321
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
322
+ const picker = new Picker(new FlatProfileStrategy());
323
+ const result = picker.run({
324
+ chunks: chronicle.chunks,
325
+ summaries: chronicle.summaries,
326
+ recallPairTokens: chronicle.recallPairTokens,
327
+ ...tailInfo,
328
+ }, BUDGET(2000, 0.1) // budget 2000, target 1800
329
+ );
330
+ assert.ok(result.budgetMet);
331
+ assert.ok(result.finalTokens <= 1800, `finalTokens ${result.finalTokens} should be ≤ targetBudget 1800`);
332
+ });
333
+ //# sourceMappingURL=picker.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.test.js","sourceRoot":"","sources":["../../../test/adaptive/picker.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=render.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.test.d.ts","sourceRoot":"","sources":["../../../test/adaptive/render.test.ts"],"names":[],"mappings":""}