@animalabs/context-manager 0.3.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 (161) 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 +74 -2
  30. package/dist/src/context-manager.d.ts.map +1 -1
  31. package/dist/src/context-manager.js +150 -10
  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 +422 -5
  41. package/dist/src/strategies/autobiographical.d.ts.map +1 -1
  42. package/dist/src/strategies/autobiographical.js +2248 -98
  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/index.d.ts +2 -2
  48. package/dist/src/types/index.d.ts.map +1 -1
  49. package/dist/src/types/index.js +1 -1
  50. package/dist/src/types/index.js.map +1 -1
  51. package/dist/src/types/message.d.ts +38 -0
  52. package/dist/src/types/message.d.ts.map +1 -1
  53. package/dist/src/types/strategy.d.ts +302 -10
  54. package/dist/src/types/strategy.d.ts.map +1 -1
  55. package/dist/src/types/strategy.js +28 -0
  56. package/dist/src/types/strategy.js.map +1 -1
  57. package/dist/test/adaptive/branching.test.d.ts +20 -0
  58. package/dist/test/adaptive/branching.test.d.ts.map +1 -0
  59. package/dist/test/adaptive/branching.test.js +176 -0
  60. package/dist/test/adaptive/branching.test.js.map +1 -0
  61. package/dist/test/adaptive/chunker.test.d.ts +2 -0
  62. package/dist/test/adaptive/chunker.test.d.ts.map +1 -0
  63. package/dist/test/adaptive/chunker.test.js +120 -0
  64. package/dist/test/adaptive/chunker.test.js.map +1 -0
  65. package/dist/test/adaptive/deep-levels.test.d.ts +10 -0
  66. package/dist/test/adaptive/deep-levels.test.d.ts.map +1 -0
  67. package/dist/test/adaptive/deep-levels.test.js +167 -0
  68. package/dist/test/adaptive/deep-levels.test.js.map +1 -0
  69. package/dist/test/adaptive/doc-plus-chat.test.d.ts +10 -0
  70. package/dist/test/adaptive/doc-plus-chat.test.d.ts.map +1 -0
  71. package/dist/test/adaptive/doc-plus-chat.test.js +194 -0
  72. package/dist/test/adaptive/doc-plus-chat.test.js.map +1 -0
  73. package/dist/test/adaptive/hard-fail.test.d.ts +9 -0
  74. package/dist/test/adaptive/hard-fail.test.d.ts.map +1 -0
  75. package/dist/test/adaptive/hard-fail.test.js +154 -0
  76. package/dist/test/adaptive/hard-fail.test.js.map +1 -0
  77. package/dist/test/adaptive/harness.d.ts +109 -0
  78. package/dist/test/adaptive/harness.d.ts.map +1 -0
  79. package/dist/test/adaptive/harness.js +263 -0
  80. package/dist/test/adaptive/harness.js.map +1 -0
  81. package/dist/test/adaptive/ingestion.test.d.ts +13 -0
  82. package/dist/test/adaptive/ingestion.test.d.ts.map +1 -0
  83. package/dist/test/adaptive/ingestion.test.js +306 -0
  84. package/dist/test/adaptive/ingestion.test.js.map +1 -0
  85. package/dist/test/adaptive/integration.test.d.ts +12 -0
  86. package/dist/test/adaptive/integration.test.d.ts.map +1 -0
  87. package/dist/test/adaptive/integration.test.js +247 -0
  88. package/dist/test/adaptive/integration.test.js.map +1 -0
  89. package/dist/test/adaptive/long-chronicle.test.d.ts +13 -0
  90. package/dist/test/adaptive/long-chronicle.test.d.ts.map +1 -0
  91. package/dist/test/adaptive/long-chronicle.test.js +186 -0
  92. package/dist/test/adaptive/long-chronicle.test.js.map +1 -0
  93. package/dist/test/adaptive/persistence.test.d.ts +11 -0
  94. package/dist/test/adaptive/persistence.test.d.ts.map +1 -0
  95. package/dist/test/adaptive/persistence.test.js +200 -0
  96. package/dist/test/adaptive/persistence.test.js.map +1 -0
  97. package/dist/test/adaptive/picker.test.d.ts +2 -0
  98. package/dist/test/adaptive/picker.test.d.ts.map +1 -0
  99. package/dist/test/adaptive/picker.test.js +333 -0
  100. package/dist/test/adaptive/picker.test.js.map +1 -0
  101. package/dist/test/adaptive/render.test.d.ts +2 -0
  102. package/dist/test/adaptive/render.test.d.ts.map +1 -0
  103. package/dist/test/adaptive/render.test.js +109 -0
  104. package/dist/test/adaptive/render.test.js.map +1 -0
  105. package/dist/test/adaptive/shard-immutability.test.d.ts +14 -0
  106. package/dist/test/adaptive/shard-immutability.test.d.ts.map +1 -0
  107. package/dist/test/adaptive/shard-immutability.test.js +184 -0
  108. package/dist/test/adaptive/shard-immutability.test.js.map +1 -0
  109. package/dist/test/adaptive/strategy-integration.test.d.ts +9 -0
  110. package/dist/test/adaptive/strategy-integration.test.d.ts.map +1 -0
  111. package/dist/test/adaptive/strategy-integration.test.js +293 -0
  112. package/dist/test/adaptive/strategy-integration.test.js.map +1 -0
  113. package/dist/test/message-store-sequence.test.d.ts +25 -0
  114. package/dist/test/message-store-sequence.test.d.ts.map +1 -0
  115. package/dist/test/message-store-sequence.test.js +157 -0
  116. package/dist/test/message-store-sequence.test.js.map +1 -0
  117. package/dist/test/non-blocking-compile.test.d.ts +22 -0
  118. package/dist/test/non-blocking-compile.test.d.ts.map +1 -0
  119. package/dist/test/non-blocking-compile.test.js +114 -0
  120. package/dist/test/non-blocking-compile.test.js.map +1 -0
  121. package/dist/test/pins.test.d.ts +10 -0
  122. package/dist/test/pins.test.d.ts.map +1 -0
  123. package/dist/test/pins.test.js +164 -0
  124. package/dist/test/pins.test.js.map +1 -0
  125. package/dist/test/recall-positioning.test.d.ts +16 -0
  126. package/dist/test/recall-positioning.test.d.ts.map +1 -0
  127. package/dist/test/recall-positioning.test.js +181 -0
  128. package/dist/test/recall-positioning.test.js.map +1 -0
  129. package/dist/test/search.test.d.ts +10 -0
  130. package/dist/test/search.test.d.ts.map +1 -0
  131. package/dist/test/search.test.js +141 -0
  132. package/dist/test/search.test.js.map +1 -0
  133. package/dist/test/speculation-cap.test.d.ts +17 -0
  134. package/dist/test/speculation-cap.test.d.ts.map +1 -0
  135. package/dist/test/speculation-cap.test.js +157 -0
  136. package/dist/test/speculation-cap.test.js.map +1 -0
  137. package/dist/test/strategy-persistence.test.d.ts +15 -0
  138. package/dist/test/strategy-persistence.test.d.ts.map +1 -0
  139. package/dist/test/strategy-persistence.test.js +244 -0
  140. package/dist/test/strategy-persistence.test.js.map +1 -0
  141. package/dist/test/tool-pruning.test.d.ts +10 -0
  142. package/dist/test/tool-pruning.test.d.ts.map +1 -0
  143. package/dist/test/tool-pruning.test.js +140 -0
  144. package/dist/test/tool-pruning.test.js.map +1 -0
  145. package/dist/tsconfig.tsbuildinfo +1 -1
  146. package/package.json +1 -1
  147. package/src/adaptive/chunker.ts +323 -0
  148. package/src/adaptive/folding-strategy.ts +129 -0
  149. package/src/adaptive/index.ts +51 -0
  150. package/src/adaptive/picker.ts +442 -0
  151. package/src/adaptive/render.ts +115 -0
  152. package/src/adaptive/strategies/flat-profile.ts +96 -0
  153. package/src/adaptive/strategies/oldest-first.ts +48 -0
  154. package/src/context-manager.ts +174 -10
  155. package/src/index.ts +1 -1
  156. package/src/message-store.ts +147 -8
  157. package/src/strategies/autobiographical.ts +2468 -166
  158. package/src/strategies/index.ts +1 -1
  159. package/src/types/index.ts +14 -1
  160. package/src/types/message.ts +43 -0
  161. package/src/types/strategy.ts +332 -10
@@ -0,0 +1,306 @@
1
+ /**
2
+ * End-to-end test of ingestion-time chunking + adaptive picker.
3
+ *
4
+ * Verifies that:
5
+ * - A large message is automatically chunked into shards at ingestion
6
+ * - Shards are stored with shared bodyGroupId
7
+ * - The picker folds shards under budget pressure
8
+ * - The render path produces ONE combined entry for the whole doc, with
9
+ * inline summary text replacing folded shards
10
+ * - Byte-faithful reassembly when no folding has happened
11
+ */
12
+ import { describe, it, before, after, beforeEach } from 'node:test';
13
+ import assert from 'node:assert/strict';
14
+ import { rmSync, existsSync } from 'node:fs';
15
+ import { ContextManager, AutobiographicalStrategy } from '../../src/index.js';
16
+ const TEST_STORE_PATH = './test-adaptive-ingestion-store';
17
+ function cleanup() {
18
+ if (existsSync(TEST_STORE_PATH)) {
19
+ rmSync(TEST_STORE_PATH, { recursive: true, force: true });
20
+ }
21
+ }
22
+ function makeMockMembrane() {
23
+ let callCount = 0;
24
+ return {
25
+ complete: async () => {
26
+ callCount++;
27
+ return {
28
+ content: [{ type: 'text', text: `[mock summary #${callCount}]` }],
29
+ };
30
+ },
31
+ get callCount() {
32
+ return callCount;
33
+ },
34
+ };
35
+ }
36
+ describe('AutobiographicalStrategy — ingestion-time chunking', () => {
37
+ before(() => cleanup());
38
+ after(() => cleanup());
39
+ beforeEach(() => cleanup());
40
+ it('flag off: large messages stay as one StoredMessage (no chunking)', async () => {
41
+ const mock = makeMockMembrane();
42
+ const strategy = new AutobiographicalStrategy({
43
+ adaptiveResolution: false,
44
+ targetChunkTokens: 100,
45
+ });
46
+ const manager = await ContextManager.open({
47
+ path: TEST_STORE_PATH,
48
+ strategy,
49
+ membrane: mock,
50
+ });
51
+ // 50K chars ≈ 12.5K tokens; well over the chunker threshold.
52
+ const bigBody = 'paragraph. '.repeat(5000);
53
+ manager.addMessage('User', [{ type: 'text', text: bigBody }]);
54
+ const all = manager.getAllMessages();
55
+ assert.equal(all.length, 1, 'flag off: should be exactly one stored message');
56
+ assert.equal(all[0].bodyGroupId, undefined);
57
+ manager.close();
58
+ });
59
+ it('flag on: large messages are sharded into multiple StoredMessages', async () => {
60
+ const mock = makeMockMembrane();
61
+ const strategy = new AutobiographicalStrategy({
62
+ adaptiveResolution: true,
63
+ targetChunkTokens: 1000, // chunker threshold ~2x = 2000
64
+ recentWindowTokens: 200,
65
+ });
66
+ const manager = await ContextManager.open({
67
+ path: TEST_STORE_PATH,
68
+ strategy,
69
+ membrane: mock,
70
+ });
71
+ // ~32K chars ≈ 8K tokens, well over chunkThreshold 2000.
72
+ const paras = [];
73
+ for (let p = 0; p < 32; p++) {
74
+ paras.push(`Paragraph ${p}: ` + 'word '.repeat(80));
75
+ }
76
+ const bigBody = paras.join('\n\n');
77
+ manager.addMessage('User', [{ type: 'text', text: bigBody }]);
78
+ const all = manager.getAllMessages();
79
+ assert.ok(all.length > 1, `expected sharding, got ${all.length} stored messages`);
80
+ // All shards should share the same bodyGroupId
81
+ const groupId = all[0].bodyGroupId;
82
+ assert.ok(groupId, 'first shard should have bodyGroupId');
83
+ for (const m of all) {
84
+ assert.equal(m.bodyGroupId, groupId, 'all shards should share bodyGroupId');
85
+ }
86
+ // shardIndex should be 0..N-1 in order
87
+ for (let idx = 0; idx < all.length; idx++) {
88
+ assert.equal(all[idx].shardIndex, idx);
89
+ }
90
+ // Byte-faithful reassembly
91
+ const reassembled = all
92
+ .map((m) => m.content.filter((b) => b.type === 'text').map((b) => b.text).join(''))
93
+ .join('');
94
+ assert.equal(reassembled, bigBody, 'concatenating shard text must equal original body');
95
+ manager.close();
96
+ });
97
+ it('flag on: compile renders bodyGroup as ONE entry with byte-faithful body (no folding)', async () => {
98
+ const mock = makeMockMembrane();
99
+ const strategy = new AutobiographicalStrategy({
100
+ adaptiveResolution: true,
101
+ targetChunkTokens: 1000,
102
+ recentWindowTokens: 50_000, // big enough that everything stays in tail (no folding)
103
+ });
104
+ const manager = await ContextManager.open({
105
+ path: TEST_STORE_PATH,
106
+ strategy,
107
+ membrane: mock,
108
+ });
109
+ const paras = [];
110
+ for (let p = 0; p < 20; p++) {
111
+ paras.push(`Para ${p}: ` + 'word '.repeat(80));
112
+ }
113
+ const bigBody = paras.join('\n\n');
114
+ manager.addMessage('User', [{ type: 'text', text: bigBody }]);
115
+ const compiled = await manager.compile({ maxTokens: 100_000, reserveForResponse: 1000 });
116
+ // Note: the doc lands in the tail window (no compression triggered).
117
+ // Tail uses newest-first eviction; the bodyGroup may render as a single
118
+ // entry OR as separate shards depending on tail emission. The current
119
+ // selectAdaptive only does bodyGroup-aware emission for the MIDDLE,
120
+ // not for the tail. So with everything in tail, we see N shards.
121
+ // For this test, we just verify compile produced output.
122
+ assert.ok(compiled.messages.length > 0, 'compile should produce output');
123
+ manager.close();
124
+ });
125
+ it('flag on: compile renders bodyGroup as combined entry under folding pressure', async () => {
126
+ const mock = makeMockMembrane();
127
+ const strategy = new AutobiographicalStrategy({
128
+ adaptiveResolution: true,
129
+ targetChunkTokens: 1000,
130
+ recentWindowTokens: 200, // small so most of the doc is in the foldable middle
131
+ });
132
+ const manager = await ContextManager.open({
133
+ path: TEST_STORE_PATH,
134
+ strategy,
135
+ membrane: mock,
136
+ });
137
+ // Big enough to require shards + at least one chunk worth of compression
138
+ const paras = [];
139
+ for (let p = 0; p < 30; p++) {
140
+ paras.push(`Para ${p}: ` + 'distinctive-token-' + p + ' word '.repeat(80));
141
+ }
142
+ const bigBody = paras.join('\n\n');
143
+ manager.addMessage('User', [{ type: 'text', text: bigBody }]);
144
+ // Add a follow-up so the doc isn't at the very end (otherwise it's all tail)
145
+ manager.addMessage('User', [{ type: 'text', text: 'Quick follow-up.' }]);
146
+ // Drive compression to completion
147
+ while (!manager.isReady()) {
148
+ await manager.tick();
149
+ }
150
+ const compiled = await manager.compile({ maxTokens: 5000, reserveForResponse: 500 });
151
+ // Find the entry that came from the bigBody shards. The middle path
152
+ // should have produced ONE combined entry (sourceRelation: 'copy' from
153
+ // the first shard) with the concatenated body — possibly with inline
154
+ // summary markers if folding happened.
155
+ assert.ok(compiled.messages.length > 0);
156
+ // The combined entry's text should be substantial (not just one shard)
157
+ // OR contain inline summary markers indicating compression happened.
158
+ const allText = compiled.messages
159
+ .flatMap((m) => m.content)
160
+ .filter((b) => b.type === 'text')
161
+ .map((b) => b.text)
162
+ .join('\n---\n');
163
+ assert.ok(allText.length > 100, `compiled output should have meaningful content; got length ${allText.length}`);
164
+ manager.close();
165
+ });
166
+ it('flag on: small messages (under threshold) are NOT chunked', async () => {
167
+ const mock = makeMockMembrane();
168
+ const strategy = new AutobiographicalStrategy({
169
+ adaptiveResolution: true,
170
+ targetChunkTokens: 1000,
171
+ });
172
+ const manager = await ContextManager.open({
173
+ path: TEST_STORE_PATH,
174
+ strategy,
175
+ membrane: mock,
176
+ });
177
+ manager.addMessage('User', [{ type: 'text', text: 'short message' }]);
178
+ const all = manager.getAllMessages();
179
+ assert.equal(all.length, 1, 'short messages should not be sharded');
180
+ assert.equal(all[0].bodyGroupId, undefined);
181
+ manager.close();
182
+ });
183
+ it('flag on: folded shards within a bodyGroup emit separate Q+A recall pair messages', async () => {
184
+ const mock = makeMockMembrane();
185
+ const strategy = new AutobiographicalStrategy({
186
+ adaptiveResolution: true,
187
+ targetChunkTokens: 300,
188
+ recentWindowTokens: 200, // small so the doc is in foldable middle
189
+ summaryContextLabel: 'What do you remember from earlier?',
190
+ summaryParticipant: 'Claude',
191
+ });
192
+ const manager = await ContextManager.open({
193
+ path: TEST_STORE_PATH,
194
+ strategy,
195
+ membrane: mock,
196
+ });
197
+ // Big doc with distinctive content per section
198
+ const paras = [];
199
+ for (let p = 0; p < 24; p++) {
200
+ paras.push(`Section ${p}: ` + `unique-token-${p} `.repeat(30));
201
+ }
202
+ const bigBody = paras.join('\n\n');
203
+ manager.addMessage('User', [{ type: 'text', text: bigBody }]);
204
+ // Trailing follow-up so the doc isn't entirely in tail
205
+ manager.addMessage('User', [{ type: 'text', text: 'Follow up please.' }]);
206
+ while (!manager.isReady()) {
207
+ await manager.tick();
208
+ }
209
+ // Compile with a budget tight enough to force folding
210
+ const compiled = await manager.compile({ maxTokens: 4000, reserveForResponse: 500 });
211
+ // Look for the Q+A recall pair pattern. If any folding happened, we
212
+ // should see "Context Manager" + summaryParticipant pairs in the
213
+ // compiled output.
214
+ const participants = compiled.messages.map((m) => m.participant);
215
+ const cmIndex = participants.indexOf('Context Manager');
216
+ const claudeIndex = participants.indexOf('Claude');
217
+ // The exact structure depends on which shards are folded and where the
218
+ // doc ends up. We assert at least one of the following holds:
219
+ // - A Q+A pair appears (Context Manager followed by Claude/summary participant)
220
+ // - OR no folding happened (everything fit at L0)
221
+ if (cmIndex >= 0) {
222
+ // Found a Q+A — there should be a Claude turn right after
223
+ assert.ok(participants[cmIndex + 1] === 'Claude' ||
224
+ participants[cmIndex + 1] === strategy['config'].summaryParticipant, `expected summary participant right after Context Manager; got ${participants[cmIndex + 1]}`);
225
+ }
226
+ // The bodyGroup should NOT be a single big composite entry with inline
227
+ // `[Section summary ...]` markers anymore. Verify no inline marker.
228
+ const allText = compiled.messages
229
+ .flatMap((m) => m.content)
230
+ .filter((b) => b.type === 'text')
231
+ .map((b) => b.text)
232
+ .join('\n');
233
+ assert.ok(!allText.includes('[Section summary ('), 'should NOT use inline [Section summary (...)] markers; should emit Q+A pairs instead');
234
+ manager.close();
235
+ });
236
+ it('flag on: tail-only bodyGroup renders as ONE composite User message (not N turns)', async () => {
237
+ const mock = makeMockMembrane();
238
+ const strategy = new AutobiographicalStrategy({
239
+ adaptiveResolution: true,
240
+ targetChunkTokens: 300,
241
+ recentWindowTokens: 100_000, // big tail so the doc fits entirely in tail
242
+ });
243
+ const manager = await ContextManager.open({
244
+ path: TEST_STORE_PATH,
245
+ strategy,
246
+ membrane: mock,
247
+ });
248
+ const paras = [];
249
+ for (let p = 0; p < 16; p++) {
250
+ paras.push(`Section ${p}: ` + 'distinctive-text '.repeat(40));
251
+ }
252
+ const bigBody = paras.join('\n\n');
253
+ manager.addMessage('User', [{ type: 'text', text: bigBody }]);
254
+ const all = manager.getAllMessages();
255
+ assert.ok(all.length > 1, 'doc should be sharded');
256
+ const compiled = await manager.compile({ maxTokens: 100_000, reserveForResponse: 1000 });
257
+ // The doc is entirely in tail. After the post-processing pass in
258
+ // selectAdaptive, it should render as exactly ONE composite User
259
+ // message — NOT N separate messages.
260
+ const userEntries = compiled.messages.filter((m) => m.participant.toLowerCase() === 'user');
261
+ assert.ok(userEntries.length > 0, 'should have user entries');
262
+ const entriesWithSection0 = userEntries.filter((m) => m.content
263
+ .filter((b) => b.type === 'text')
264
+ .some((b) => b.text.includes('Section 0:')));
265
+ assert.equal(entriesWithSection0.length, 1, 'Section 0 should appear in exactly one user entry (composite)');
266
+ const compositeEntry = entriesWithSection0[0];
267
+ const compositeText = compositeEntry.content
268
+ .filter((b) => b.type === 'text')
269
+ .map((b) => b.text)
270
+ .join('');
271
+ assert.ok(compositeText.includes('Section 15:'), 'composite should also contain the last section (all shards merged)');
272
+ assert.equal(compositeText, bigBody, 'composite text should reassemble original body byte-for-byte');
273
+ manager.close();
274
+ });
275
+ it('flag on: non-text content (e.g., tool_use blocks) is preserved on first shard', async () => {
276
+ const mock = makeMockMembrane();
277
+ const strategy = new AutobiographicalStrategy({
278
+ adaptiveResolution: true,
279
+ targetChunkTokens: 500,
280
+ });
281
+ const manager = await ContextManager.open({
282
+ path: TEST_STORE_PATH,
283
+ strategy,
284
+ membrane: mock,
285
+ });
286
+ // A big text payload + a tool_use-like non-text block
287
+ const bigText = 'paragraph. '.repeat(2000);
288
+ manager.addMessage('User', [
289
+ { type: 'text', text: bigText },
290
+ // A simulated non-text block; the chunker passes it through.
291
+ { type: 'tool_use', id: 'tool-1', name: 'search', input: { q: 'test' } },
292
+ ]);
293
+ const all = manager.getAllMessages();
294
+ assert.ok(all.length > 1, 'should be sharded');
295
+ // First shard should carry the non-text block(s)
296
+ const firstNonText = all[0].content.filter((b) => b.type !== 'text');
297
+ assert.equal(firstNonText.length, 1, 'first shard should carry the tool_use block');
298
+ // Other shards should not
299
+ for (let idx = 1; idx < all.length; idx++) {
300
+ const nonText = all[idx].content.filter((b) => b.type !== 'text');
301
+ assert.equal(nonText.length, 0, `shard ${idx} should not carry tool_use`);
302
+ }
303
+ manager.close();
304
+ });
305
+ });
306
+ //# sourceMappingURL=ingestion.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingestion.test.js","sourceRoot":"","sources":["../../../test/adaptive/ingestion.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Integration tests for the adaptive-resolution picker.
3
+ *
4
+ * These simulate realistic scenarios over many turns and verify the
5
+ * design's claimed properties end-to-end:
6
+ * - 500K-doc ingestion + first compile fits in budget
7
+ * - 200-turn growth with picker firing only as needed
8
+ * - Monotonic cache stickiness (a chunk's resolution only ever rises)
9
+ * - Group-fold operates correctly through chained levels
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../../test/adaptive/integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Integration tests for the adaptive-resolution picker.
3
+ *
4
+ * These simulate realistic scenarios over many turns and verify the
5
+ * design's claimed properties end-to-end:
6
+ * - 500K-doc ingestion + first compile fits in budget
7
+ * - 200-turn growth with picker firing only as needed
8
+ * - Monotonic cache stickiness (a chunk's resolution only ever rises)
9
+ * - Group-fold operates correctly through chained levels
10
+ */
11
+ import { test } from 'node:test';
12
+ import assert from 'node:assert/strict';
13
+ import { Picker } from '../../src/adaptive/picker.js';
14
+ import { FlatProfileStrategy } from '../../src/adaptive/strategies/flat-profile.js';
15
+ import { chunkMessage } from '../../src/adaptive/chunker.js';
16
+ import { MockChronicle } from './harness.js';
17
+ const BUDGET = (totalBudget, slack = 0.1) => ({
18
+ totalBudget,
19
+ targetBudget: totalBudget * (1 - slack),
20
+ slack,
21
+ });
22
+ test('integration: 500K doc ingested as shards + picker folds to fit 30K budget', () => {
23
+ // Synthetic 500K-char body. Real 500K-token doc would be ~2M chars.
24
+ // We use char-equivalent here for test speed; chunker uses charsPerToken=4 by default.
25
+ const synthetic500K = Array.from({ length: 125 }, (_, i) => {
26
+ return `## Section ${i}\n\n` + 'Lorem ipsum dolor sit amet. '.repeat(140); // ~3920 chars per section ≈ 4K chars ≈ 1K tokens
27
+ }).join('\n\n');
28
+ // Chunk
29
+ const sharded = chunkMessage(synthetic500K, { chunkThreshold: 8192, chunkSize: 4096, charsPerToken: 4 });
30
+ assert.equal(sharded.wasSharded, true);
31
+ const shardCount = sharded.shards.length;
32
+ assert.ok(shardCount >= 30, `expected ≥30 shards from 500K-char synthetic doc, got ${shardCount}`);
33
+ // Build chronicle
34
+ const chronicle = new MockChronicle({ mergeThreshold: 6, recallPairTokens: 200 });
35
+ for (const s of sharded.shards) {
36
+ chronicle.addChunk({
37
+ id: `doc-${s.index.toString().padStart(4, '0')}`,
38
+ rawTokens: s.approxTokens,
39
+ bodyGroupId: sharded.bodyGroupId,
40
+ });
41
+ }
42
+ // Pre-produce summaries (mimics the speculative pre-producer running at ingestion)
43
+ for (let i = 0; i < chronicle.chunks.length; i += chronicle.mergeThreshold) {
44
+ chronicle.produceL1(chronicle.chunks.slice(i, i + chronicle.mergeThreshold).map((c) => c.id));
45
+ }
46
+ chronicle.preProduceUpperLevels();
47
+ // Compile with budget 30K
48
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 0 });
49
+ const picker = new Picker(new FlatProfileStrategy());
50
+ const result = picker.run({
51
+ chunks: chronicle.chunks,
52
+ summaries: chronicle.summaries,
53
+ recallPairTokens: chronicle.recallPairTokens,
54
+ ...tailInfo,
55
+ }, BUDGET(30_000));
56
+ // Should converge with budget met
57
+ assert.equal(result.budgetMet, true, `picker should meet budget; final tokens = ${result.finalTokens}`);
58
+ assert.ok(result.finalTokens <= 27_000, `final tokens ${result.finalTokens} should be ≤ targetBudget 27000`);
59
+ });
60
+ test('integration: 200-turn conversation growth — picker fires only as needed (steady-state cache)', () => {
61
+ const chronicle = new MockChronicle({ mergeThreshold: 6, recallPairTokens: 200 });
62
+ const picker = new Picker(new FlatProfileStrategy());
63
+ const BUDGET_TOTAL = 5000;
64
+ // Track how many turns invoke the picker (i.e., apply any folds).
65
+ let pickerFiredTurns = 0;
66
+ let totalRaises = 0;
67
+ // Per-chunk resolution history — verify monotonicity.
68
+ const resolutionHistory = new Map();
69
+ for (let turn = 0; turn < 200; turn++) {
70
+ // Each turn adds a new "message" chunk of ~50 tokens.
71
+ chronicle.addChunk({ id: `m-${turn.toString().padStart(4, '0')}`, rawTokens: 50 });
72
+ // Periodically produce L1s as the compression queue would (every 6 chunks).
73
+ if (chronicle.chunks.length % 6 === 0) {
74
+ const start = chronicle.chunks.length - 6;
75
+ chronicle.produceL1(chronicle.chunks.slice(start, start + 6).map((c) => c.id));
76
+ chronicle.preProduceUpperLevels();
77
+ }
78
+ // Run picker
79
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 500 });
80
+ const result = picker.run({
81
+ chunks: chronicle.chunks,
82
+ summaries: chronicle.summaries,
83
+ recallPairTokens: chronicle.recallPairTokens,
84
+ ...tailInfo,
85
+ }, BUDGET(BUDGET_TOTAL));
86
+ if (result.applied.length > 0) {
87
+ pickerFiredTurns++;
88
+ totalRaises += result.applied.length;
89
+ }
90
+ chronicle.applyResolutions(result.finalResolutions);
91
+ // Record resolution per chunk
92
+ for (const c of chronicle.chunks) {
93
+ const arr = resolutionHistory.get(c.id) ?? [];
94
+ arr.push(c.currentResolution);
95
+ resolutionHistory.set(c.id, arr);
96
+ }
97
+ }
98
+ // Monotonicity check: every chunk's resolution sequence should be non-decreasing.
99
+ for (const [id, history] of resolutionHistory) {
100
+ for (let i = 1; i < history.length; i++) {
101
+ assert.ok(history[i] >= history[i - 1], `chunk ${id} resolution decreased at step ${i}: ${history[i - 1]} → ${history[i]}`);
102
+ }
103
+ }
104
+ // Picker should fire on a MINORITY of turns (cache stickiness property).
105
+ assert.ok(pickerFiredTurns < 200 * 0.5, `picker fired on ${pickerFiredTurns}/200 turns; should fire less than half the time`);
106
+ // Most turns are no-ops in steady state.
107
+ const noOpTurns = 200 - pickerFiredTurns;
108
+ assert.ok(noOpTurns > 100, `expected at least 100 no-op turns, got ${noOpTurns}`);
109
+ });
110
+ test('integration: bodyGroupId chunks fold independently within one doc', () => {
111
+ // Build a doc with 18 shards (3 L1 groups). Force partial folding so some
112
+ // shards are L0 and some are L1, verifying that the per-chunk state allows
113
+ // mixed resolution within a single bodyGroup.
114
+ const chronicle = new MockChronicle({ mergeThreshold: 6, recallPairTokens: 100 });
115
+ for (let i = 0; i < 18; i++) {
116
+ chronicle.addChunk({
117
+ id: `doc-${i.toString().padStart(4, '0')}`,
118
+ rawTokens: 500,
119
+ bodyGroupId: 'doc-1',
120
+ });
121
+ }
122
+ for (let i = 0; i < 18; i += 6) {
123
+ chronicle.produceL1(chronicle.chunks.slice(i, i + 6).map((c) => c.id));
124
+ }
125
+ chronicle.preProduceUpperLevels(); // 3 L1s won't produce L2 (need 6)
126
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 500 });
127
+ const picker = new Picker(new FlatProfileStrategy());
128
+ const result = picker.run({
129
+ chunks: chronicle.chunks,
130
+ summaries: chronicle.summaries,
131
+ recallPairTokens: chronicle.recallPairTokens,
132
+ ...tailInfo,
133
+ }, BUDGET(5000) // 17 chunks (excl tail) × 500 = 8500 raw; target 4500
134
+ );
135
+ // Should have folded some chunks (oldest L1 group) but not all.
136
+ let l0Count = 0;
137
+ let l1Count = 0;
138
+ for (const c of chronicle.chunks) {
139
+ const r = result.finalResolutions.get(c.id) ?? c.currentResolution;
140
+ if (r === 0)
141
+ l0Count++;
142
+ else if (r === 1)
143
+ l1Count++;
144
+ }
145
+ assert.ok(l0Count > 0 && l1Count > 0, `expected mixed L0+L1 within doc, got L0=${l0Count} L1=${l1Count}`);
146
+ });
147
+ test('integration: lockedByAgent prevents picker from raising a chunk', () => {
148
+ const chronicle = new MockChronicle({ mergeThreshold: 6, recallPairTokens: 200 });
149
+ for (let i = 0; i < 12; i++) {
150
+ chronicle.addChunk({ id: `c-${i.toString().padStart(4, '0')}`, rawTokens: 100 });
151
+ }
152
+ for (let i = 0; i < 12; i += 6) {
153
+ chronicle.produceL1(chronicle.chunks.slice(i, i + 6).map((c) => c.id));
154
+ }
155
+ // Lock chunk c-0002 by setting lockedByAgent directly. In production this
156
+ // is set via AutobiographicalStrategy.lockChunk(id); here we exercise the
157
+ // picker's contract that lockedByAgent freezes a chunk's resolution.
158
+ const lockChunk = (id) => {
159
+ for (const c of chronicle.chunks)
160
+ if (c.id === id)
161
+ c.lockedByAgent = true;
162
+ };
163
+ const unlockChunk = (id) => {
164
+ for (const c of chronicle.chunks)
165
+ if (c.id === id)
166
+ c.lockedByAgent = false;
167
+ };
168
+ const isLocked = (id) => chronicle.chunks.find((c) => c.id === id)?.lockedByAgent === true;
169
+ lockChunk('c-0002');
170
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
171
+ const picker = new Picker(new FlatProfileStrategy());
172
+ const result = picker.run({
173
+ chunks: chronicle.chunks,
174
+ summaries: chronicle.summaries,
175
+ recallPairTokens: chronicle.recallPairTokens,
176
+ ...tailInfo,
177
+ }, BUDGET(900));
178
+ // c-0002 should remain at L0 despite siblings being raised.
179
+ assert.equal(result.finalResolutions.get('c-0002'), 0);
180
+ // Siblings should be at L1 if the picker ran the first group fold.
181
+ if (result.finalResolutions.get('c-0000') === 1) {
182
+ for (const sibling of ['c-0000', 'c-0001', 'c-0003', 'c-0004', 'c-0005']) {
183
+ assert.equal(result.finalResolutions.get(sibling), 1, `${sibling} should be L1`);
184
+ }
185
+ }
186
+ assert.equal(isLocked('c-0002'), true);
187
+ // Unlock and verify the lock state is cleared.
188
+ unlockChunk('c-0002');
189
+ assert.equal(isLocked('c-0002'), false);
190
+ chronicle.applyResolutions(result.finalResolutions);
191
+ // Without new pressure, the picker won't refire — that's correct
192
+ // (monotonic, stingy). But under fresh pressure, c-0002 is now eligible.
193
+ // Simulate new pressure by adding many new L0 chunks.
194
+ for (let i = 12; i < 30; i++) {
195
+ chronicle.addChunk({ id: `c-${i.toString().padStart(4, '0')}`, rawTokens: 100 });
196
+ }
197
+ for (let i = 12; i < 30; i += 6) {
198
+ chronicle.produceL1(chronicle.chunks.slice(i, i + 6).map((c) => c.id));
199
+ }
200
+ chronicle.preProduceUpperLevels();
201
+ const tailInfo2 = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 100 });
202
+ const result2 = picker.run({
203
+ chunks: chronicle.chunks,
204
+ summaries: chronicle.summaries,
205
+ recallPairTokens: chronicle.recallPairTokens,
206
+ ...tailInfo2,
207
+ }, BUDGET(900));
208
+ // Now under enough pressure that c-0002's group should fully collapse.
209
+ // The L1-0 group covers c-0000..c-0005. With c-0002 unlocked, applyRaise
210
+ // can include it. After enough pressure, c-0002 should be at L1.
211
+ const finalRes = result2.finalResolutions.get('c-0002');
212
+ assert.ok((finalRes ?? 0) >= 1, `after unlock + new pressure, c-0002 should be ≥ L1 (got ${finalRes})`);
213
+ });
214
+ test('integration: stress — 1000 chunks, deep recursion via preProduceUpperLevels', () => {
215
+ // Sanity check that the harness scales and the picker doesn't blow up.
216
+ const chronicle = new MockChronicle({ mergeThreshold: 6, recallPairTokens: 200 });
217
+ for (let i = 0; i < 1000; i++) {
218
+ chronicle.addChunk({ id: `c-${i.toString().padStart(4, '0')}`, rawTokens: 100 });
219
+ }
220
+ for (let i = 0; i < 1000; i += 6) {
221
+ const slice = chronicle.chunks.slice(i, Math.min(i + 6, 1000));
222
+ if (slice.length === 6) {
223
+ chronicle.produceL1(slice.map((c) => c.id));
224
+ }
225
+ }
226
+ chronicle.preProduceUpperLevels();
227
+ // Expect summaries at multiple levels: 1000/6 ≈ 167 L1s, 167/6 ≈ 27 L2s, 27/6 = 4 L3s, no L4 yet.
228
+ const levels = new Set();
229
+ for (const s of chronicle.summaries.values())
230
+ levels.add(s.level);
231
+ assert.ok(levels.has(1) && levels.has(2) && levels.has(3), `expected L1, L2, L3; got ${Array.from(levels)}`);
232
+ const tailInfo = chronicle.computeHeadTail({ headTokens: 0, tailTokens: 500 });
233
+ const picker = new Picker(new FlatProfileStrategy());
234
+ const start = Date.now();
235
+ const result = picker.run({
236
+ chunks: chronicle.chunks,
237
+ summaries: chronicle.summaries,
238
+ recallPairTokens: chronicle.recallPairTokens,
239
+ ...tailInfo,
240
+ }, BUDGET(10_000));
241
+ const elapsed = Date.now() - start;
242
+ assert.ok(elapsed < 5000, `picker took ${elapsed}ms on 1000 chunks; should be < 5s`);
243
+ assert.ok(result.iterations < 1000, `should converge in fewer than 1000 iterations, got ${result.iterations}`);
244
+ // Budget should be met or production requested
245
+ assert.ok(result.budgetMet || result.produced.length > 0);
246
+ });
247
+ //# sourceMappingURL=integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../../../test/adaptive/integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * End-to-end stress test: a long-running chronicle with mixed content.
3
+ *
4
+ * Simulates 200+ turns of conversation, with a big doc dropped in the middle,
5
+ * and verifies:
6
+ * - Compile output never exceeds the budget (the picker actually does its job)
7
+ * - Resolutions monotone over the run (no thrashing)
8
+ * - Picker is idle on most turns (steady-state cache property)
9
+ * - Final state can be reloaded cleanly
10
+ * - Output structure remains sensible across the run
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=long-chronicle.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"long-chronicle.test.d.ts","sourceRoot":"","sources":["../../../test/adaptive/long-chronicle.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}