strong owner

This commit is contained in:
Your Name
2026-05-14 03:04:19 +00:00
parent d0032c6749
commit c7ba026c18
24 changed files with 1105 additions and 770 deletions
@@ -5,6 +5,7 @@
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { randomUUID } from 'node:crypto';
import { testTruncateProfile } from './testing/testProfile.js';
import {
createSyntheticHistory,
@@ -32,20 +33,29 @@ describe('ContextManager Sync Pressure Barrier Tests', () => {
// 2. Add System Prompt (Episode 0 - Protected)
chatHistory.set([
{ role: 'user', parts: [{ text: 'System prompt' }] },
{ role: 'model', parts: [{ text: 'Understood.' }] },
{ id: 'h1', content: { role: 'user', parts: [{ text: 'System prompt' }] } },
{ id: 'h2', content: { role: 'model', parts: [{ text: 'Understood.' }] } },
]);
// 3. Add massive history that blows past the 150k maxTokens limit
// 20 turns * ~20,000 tokens/turn (10k user + 10k model) = ~400,000 tokens
const massiveHistory = createSyntheticHistory(20, 10000);
const massiveHistory = createSyntheticHistory(20, 10000).map((c) => ({
id: randomUUID(),
content: c,
}));
chatHistory.set([...chatHistory.get(), ...massiveHistory]);
// 4. Add the Latest Turn (Protected)
chatHistory.set([
...chatHistory.get(),
{ role: 'user', parts: [{ text: 'Final question.' }] },
{ role: 'model', parts: [{ text: 'Final answer.' }] },
{
id: 'h-last-user',
content: { role: 'user', parts: [{ text: 'Final question.' }] },
},
{
id: 'h-last-model',
content: { role: 'model', parts: [{ text: 'Final answer.' }] },
},
]);
const rawHistoryLength = chatHistory.get().length;
@@ -59,21 +69,22 @@ describe('ContextManager Sync Pressure Barrier Tests', () => {
expect(projection.length).toBeLessThan(rawHistoryLength);
// Verify Episode 0 (System) was pruned, so we now start with a sentinel due to role alternation
expect(projection[0].role).toBe('user');
expect(projection[0].content.role).toBe('user');
const projectionString = JSON.stringify(projection);
expect(projectionString).toContain('User turn 17');
// Filter out synthetic Yield nodes (they are model responses without actual tool/text bodies)
const contentNodes = projection.filter(
(p) =>
p.parts && p.parts.some((part) => part.text && part.text !== 'Yield'),
p.content.parts &&
p.content.parts.some((part) => part.text && part.text !== 'Yield'),
);
// Verify the latest turn is perfectly preserved at the back
// Note: The HistoryHardener appends a "Please continue." user turn if we end on model,
// so we look at the turns before the sentinel.
const lastSentinel = contentNodes[contentNodes.length - 1];
const lastModel = contentNodes[contentNodes.length - 2];
const lastUser = contentNodes[contentNodes.length - 3];
const lastSentinel = contentNodes[contentNodes.length - 1].content;
const lastModel = contentNodes[contentNodes.length - 2].content;
const lastUser = contentNodes[contentNodes.length - 3].content;
expect(lastSentinel.role).toBe('user');
expect(lastSentinel.parts![0].text).toBe('Please continue.');