refactor: optimize inner-loop-tracker performance and code quality

Performance improvements:
- Throttle cleanupExpiredTodos() to run every 30s instead of every chunk
- Add early exit in detectTodoItems() for lines without todo markers
- Remove redundant PROMISE_PATTERN check from LOOP_START_PATTERN

Code quality:
- Extract activateLoopIfNeeded() helper to eliminate duplicate loop start logic
- Improve hash function using djb2 algorithm for better distribution
- Add guards for empty/whitespace-only content in upsertTodo()
- Simplify startLoop() to use existing enable() method

Tests:
- Add 5 new tests for edge cases and optimizations
- Test empty content handling, early exit, ID uniqueness

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-20 15:16:22 +01:00
co-authored by Claude Opus 4.5
parent af9290389c
commit bc16459ecb
2 changed files with 121 additions and 51 deletions
+59
View File
@@ -613,4 +613,63 @@ describe('InnerLoopTracker', () => {
expect(tracker.todos.length).toBeLessThanOrEqual(50);
});
});
describe('Edge Cases and Optimizations', () => {
it('should skip empty or whitespace-only content', () => {
// These should not create todos
tracker.processTerminalData('- [ ] \n');
tracker.processTerminalData('- [ ] \n');
expect(tracker.todos).toHaveLength(0);
});
it('should skip lines without todo markers (early exit optimization)', () => {
const todoHandler = vi.fn();
tracker.on('todoUpdate', todoHandler);
// Process lines that have no todo markers
tracker.processTerminalData('This is just regular text\n');
tracker.processTerminalData('Another line without markers\n');
tracker.processTerminalData('Some code: function() {}\n');
// No todoUpdate should be emitted
expect(todoHandler).not.toHaveBeenCalled();
expect(tracker.todos).toHaveLength(0);
});
it('should generate different IDs for different content', () => {
tracker.processTerminalData('- [ ] Task A\n');
tracker.processTerminalData('- [ ] Task B\n');
const todos = tracker.todos;
expect(todos).toHaveLength(2);
expect(todos[0].id).not.toBe(todos[1].id);
});
it('should use activateLoopIfNeeded only once', () => {
const loopHandler = vi.fn();
tracker.on('loopUpdate', loopHandler);
// Multiple loop start patterns should only activate once
tracker.processTerminalData('Loop started at 2024-01-15\n');
tracker.processTerminalData('Starting Ralph loop\n');
tracker.processTerminalData('/ralph-loop:ralph-loop\n');
// Loop should only have been activated once
expect(tracker.loopState.active).toBe(true);
// But multiple updates are OK (state changes)
});
it('should handle mixed content with todos and non-todos', () => {
tracker.processTerminalData(`
Some regular text
- [ ] Actual todo item
More text here
☐ Another todo with icon
Final text
`);
expect(tracker.todos).toHaveLength(2);
});
});
});