Files
Dragan Spiridonov e82a7240ec feat: implement CC-internals improvements IMP-00 through IMP-10 (Waves 0-4)
11 improvements across 4 priority tiers, all integrated into production
code paths with 416 new tests across 33 test files. Each wave passed
a brutal honesty audit with all findings resolved.

Wave 0-2 (P0/P1): Middleware chain, microcompact, tool concurrency,
retry engine, session durability, prompt cache latch, startup fast
paths, hook security hardening.

Wave 3 (P2): 4-tier context compaction pipeline, plugin architecture
with local/GitHub/npm sources.

Wave 4 (P3): QE Quality Daemon — priority queue, git watcher (with
Linux polling fallback), coverage delta analyzer, CI monitor, test
suggester, nightly consolidation, notification service with SSRF guard,
persistent SQLite-backed memory, CLI commands, MCP startup integration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 17:32:50 +00:00

119 lines
4.4 KiB
TypeScript

/**
* Tests for Tier4Reactive (IMP-08)
*/
import { describe, it, expect } from 'vitest';
import { Tier4Reactive } from '../../../src/context/compaction/tier4-reactive';
import type { ConversationMessage } from '../../../src/context/compaction/tier2-session-summary';
function makeMsg(role: ConversationMessage['role'], content: string, extra?: Partial<ConversationMessage>): ConversationMessage {
return { role, content, timestamp: Date.now(), ...extra };
}
describe('Tier4Reactive', () => {
const tier4 = new Tier4Reactive({ recoveryTarget: 500, minPreservedMessages: 2 });
describe('empty input', () => {
it('should handle empty messages', () => {
const result = tier4.compact([], 'context_overflow');
expect(result.tier).toBe(4);
expect(result.survivingMessages).toHaveLength(0);
expect(result.droppedCount).toBe(0);
});
});
describe('already under target', () => {
it('should return all messages if already under recovery target', () => {
const messages: ConversationMessage[] = [
makeMsg('user', 'hi'),
makeMsg('assistant', 'hello'),
];
const result = tier4.compact(messages);
expect(result.droppedCount).toBe(0);
expect(result.survivingMessages).toHaveLength(2);
expect(result.tokensSaved).toBe(0);
});
});
describe('aggressive peeling', () => {
it('should drop oldest messages to get under recovery target', () => {
const messages: ConversationMessage[] = [];
// Create 10 messages, each ~100 tokens (300 chars / 3)
for (let i = 0; i < 10; i++) {
messages.push(makeMsg('user', `Message ${i}: ${'x'.repeat(300)}`));
}
const result = tier4.compact(messages, 'status_413');
expect(result.trigger).toBe('status_413');
expect(result.droppedCount).toBeGreaterThan(0);
expect(result.survivingTokens).toBeLessThanOrEqual(600); // some tolerance
expect(result.tokensSaved).toBeGreaterThan(0);
});
it('should preserve minimum tail messages', () => {
const messages: ConversationMessage[] = [];
for (let i = 0; i < 10; i++) {
messages.push(makeMsg('user', 'x'.repeat(300)));
}
const result = tier4.compact(messages);
// minPreservedMessages = 2
expect(result.survivingMessages.length).toBeGreaterThanOrEqual(2);
});
});
describe('tool pair handling', () => {
it('should drop tool_use and tool_result pairs together', () => {
const messages: ConversationMessage[] = [
makeMsg('tool_use', 'x'.repeat(300), { toolUseId: 'pair-1', toolName: 'test' }),
makeMsg('tool_result', 'y'.repeat(300), { toolUseId: 'pair-1' }),
makeMsg('user', 'short'), // preserved tail
makeMsg('assistant', 'ok'), // preserved tail
];
const result = tier4.compact(messages);
// If one of the pair was dropped, both should be dropped
const surviving = result.survivingMessages;
const hasTU = surviving.some(m => m.role === 'tool_use' && m.toolUseId === 'pair-1');
const hasTR = surviving.some(m => m.role === 'tool_result' && m.toolUseId === 'pair-1');
// Either both survived or neither
expect(hasTU).toBe(hasTR);
});
});
describe('isContextOverflow', () => {
it('should detect 413 status code', () => {
expect(Tier4Reactive.isContextOverflow(413)).toBe(true);
expect(Tier4Reactive.isContextOverflow(200)).toBe(false);
});
it('should detect context_length_exceeded in error message', () => {
expect(Tier4Reactive.isContextOverflow('context_length_exceeded')).toBe(true);
});
it('should detect maximum context length in error message', () => {
expect(Tier4Reactive.isContextOverflow('Error: maximum context length reached')).toBe(true);
});
it('should detect too many tokens', () => {
expect(Tier4Reactive.isContextOverflow('too many tokens in request')).toBe(true);
});
it('should return false for unrelated messages', () => {
expect(Tier4Reactive.isContextOverflow('connection timeout')).toBe(false);
});
});
describe('trigger types', () => {
it('should record trigger type in result', () => {
const messages = [makeMsg('user', 'x'.repeat(1000))];
expect(tier4.compact(messages, 'status_413').trigger).toBe('status_413');
expect(tier4.compact(messages, 'context_overflow').trigger).toBe('context_overflow');
expect(tier4.compact(messages, 'manual').trigger).toBe('manual');
});
});
});