@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,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":""}
@@ -0,0 +1,109 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { chunkMessage } from '../../src/adaptive/chunker.js';
4
+ import { concatBodyGroups, placeholderRecallText } from '../../src/adaptive/render.js';
5
+ function makeShard(body, groupId, shardIndex, options = {}) {
6
+ return {
7
+ id: `${groupId}-shard-${shardIndex}`,
8
+ sequence: shardIndex,
9
+ participant: 'User',
10
+ content: [{ type: 'text', text: body }],
11
+ timestamp: new Date(0),
12
+ bodyGroupId: groupId,
13
+ shardIndex,
14
+ ...options,
15
+ };
16
+ }
17
+ function makePlainMessage(id, body, sequence = 0) {
18
+ return {
19
+ id,
20
+ sequence,
21
+ participant: 'User',
22
+ content: [{ type: 'text', text: body }],
23
+ timestamp: new Date(0),
24
+ };
25
+ }
26
+ test('render: messages without bodyGroupId pass through unchanged', () => {
27
+ const messages = [
28
+ makePlainMessage('m-1', 'hello', 0),
29
+ makePlainMessage('m-2', 'world', 1),
30
+ ];
31
+ const out = concatBodyGroups(messages, placeholderRecallText);
32
+ assert.equal(out.length, 2);
33
+ assert.equal(out[0].id, 'm-1');
34
+ assert.equal(out[1].id, 'm-2');
35
+ });
36
+ test('render: byte-faithful concat for all-L0 shards', () => {
37
+ const originalBody = 'a'.repeat(200) + '\n\n' + 'b'.repeat(200) + '\n\n' + 'c'.repeat(200);
38
+ const sharded = chunkMessage(originalBody, { chunkThreshold: 50, chunkSize: 50, charsPerToken: 1.0 });
39
+ assert.equal(sharded.wasSharded, true);
40
+ // Build StoredMessages from the shards
41
+ const messages = sharded.shards.map((s) => makeShard(s.content, sharded.bodyGroupId, s.index));
42
+ const concatenated = concatBodyGroups(messages, placeholderRecallText);
43
+ assert.equal(concatenated.length, 1, 'all shards should merge into one composite');
44
+ const block = concatenated[0].content[0];
45
+ assert.equal(block.type, 'text');
46
+ const text = block.text;
47
+ assert.equal(text, originalBody, 'concatenated body must equal original byte-for-byte');
48
+ });
49
+ test('render: shard at L1 emits recall text instead of raw', () => {
50
+ const shard0 = makeShard('first shard ', 'g-1', 0);
51
+ const shard1 = makeShard('second shard ', 'g-1', 1, { currentResolution: 1 });
52
+ const shard2 = makeShard('third shard', 'g-1', 2);
53
+ const concatenated = concatBodyGroups([shard0, shard1, shard2], (s) => `<<recall:${s.id}>>`);
54
+ assert.equal(concatenated.length, 1);
55
+ const text = concatenated[0].content[0].text;
56
+ assert.equal(text, 'first shard <<recall:g-1-shard-1>>third shard');
57
+ });
58
+ test('render: multiple bodyGroups remain separate', () => {
59
+ const g1s0 = makeShard('hello ', 'g-1', 0);
60
+ const g1s1 = makeShard('world', 'g-1', 1);
61
+ const g2s0 = makeShard('foo ', 'g-2', 0);
62
+ const g2s1 = makeShard('bar', 'g-2', 1);
63
+ const concatenated = concatBodyGroups([g1s0, g1s1, g2s0, g2s1], placeholderRecallText);
64
+ assert.equal(concatenated.length, 2);
65
+ assert.equal(concatenated[0].content[0].text, 'hello world');
66
+ assert.equal(concatenated[1].content[0].text, 'foo bar');
67
+ });
68
+ test('render: shard order honored even if input is out of order', () => {
69
+ const s0 = makeShard('A', 'g', 0);
70
+ const s1 = makeShard('B', 'g', 1);
71
+ const s2 = makeShard('C', 'g', 2);
72
+ // Note: the input order here would actually break grouping because we
73
+ // group by *consecutive* same-bodyGroupId — out-of-order input means
74
+ // the group is broken if a different one interrupts. But within a
75
+ // contiguous run, shardIndex determines concat order.
76
+ const concatenated = concatBodyGroups([s2, s0, s1], placeholderRecallText);
77
+ assert.equal(concatenated.length, 1);
78
+ const text = concatenated[0].content[0].text;
79
+ assert.equal(text, 'ABC');
80
+ });
81
+ test('render: interleaved plain + grouped messages preserve order', () => {
82
+ const plain1 = makePlainMessage('p-1', 'plain text 1', 0);
83
+ const g1s0 = makeShard('group ', 'g-1', 0);
84
+ const g1s1 = makeShard('one', 'g-1', 1);
85
+ const plain2 = makePlainMessage('p-2', 'plain text 2', 3);
86
+ const g2s0 = makeShard('group ', 'g-2', 0);
87
+ const g2s1 = makeShard('two', 'g-2', 1);
88
+ const concatenated = concatBodyGroups([plain1, g1s0, g1s1, plain2, g2s0, g2s1], placeholderRecallText);
89
+ assert.equal(concatenated.length, 4);
90
+ assert.equal(concatenated[0].id, 'p-1');
91
+ assert.equal(concatenated[1].content[0].text, 'group one');
92
+ assert.equal(concatenated[2].id, 'p-2');
93
+ assert.equal(concatenated[3].content[0].text, 'group two');
94
+ });
95
+ test('render: chunker + render round-trips with realistic large doc', () => {
96
+ // Build a synthetic doc, chunk it, render it back, verify byte-identical.
97
+ const paragraphs = [];
98
+ for (let i = 0; i < 50; i++) {
99
+ paragraphs.push(`# Section ${i}\n\nThis is the content of section ${i}. ` + 'Lorem ipsum dolor sit amet. '.repeat(20));
100
+ }
101
+ const body = paragraphs.join('\n\n');
102
+ const sharded = chunkMessage(body); // default options
103
+ const messages = sharded.shards.map((s) => makeShard(s.content, sharded.bodyGroupId, s.index));
104
+ const concatenated = concatBodyGroups(messages, placeholderRecallText);
105
+ assert.equal(concatenated.length, 1);
106
+ const text = concatenated[0].content[0].text;
107
+ assert.equal(text, body);
108
+ });
109
+ //# sourceMappingURL=render.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.test.js","sourceRoot":"","sources":["../../../test/adaptive/render.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Tests that the message store rejects operations that would corrupt a
3
+ * bodyGroup's byte-faithful reassembly invariant:
4
+ * - editMessage on a shard
5
+ * - removeMessage on a single shard (without removing the rest)
6
+ * - removeRange that bisects a bodyGroup
7
+ *
8
+ * Provides removeBodyGroup as the atomic way to drop a sharded message.
9
+ *
10
+ * Also verifies pins-in-adaptive (Fix #1) and maxMessageTokens not applied
11
+ * to bodyGroup composites (Fix #3) for completeness.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=shard-immutability.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shard-immutability.test.d.ts","sourceRoot":"","sources":["../../../test/adaptive/shard-immutability.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}