diff --git a/src/features/context-injector/collector.test.ts b/src/features/context-injector/collector.test.ts index 695ff4af8..4001b5483 100644 --- a/src/features/context-injector/collector.test.ts +++ b/src/features/context-injector/collector.test.ts @@ -205,6 +205,45 @@ describe("ContextCollector", () => { const ids = pending.entries.map((e) => e.id) expect(ids).toEqual(["first", "second", "third"]) }) + + it("keeps registration order even when Date.now values are not monotonic", () => { + // given + const sessionID = "ses_order_non_monotonic_time" + const originalDateNow = Date.now + const mockedTimestamps = [300, 100, 200] + let timestampIndex = 0 + Date.now = () => mockedTimestamps[timestampIndex++] ?? 0 + + try { + collector.register(sessionID, { + id: "first", + source: "custom", + content: "First", + priority: "normal", + }) + collector.register(sessionID, { + id: "second", + source: "custom", + content: "Second", + priority: "normal", + }) + collector.register(sessionID, { + id: "third", + source: "custom", + content: "Third", + priority: "normal", + }) + } finally { + Date.now = originalDateNow + } + + // when + const pending = collector.getPending(sessionID) + + // then + const ids = pending.entries.map((entry) => entry.id) + expect(ids).toEqual(["first", "second", "third"]) + }) }) describe("consume", () => { diff --git a/src/features/context-injector/collector.ts b/src/features/context-injector/collector.ts index af60e4196..f1b9f61ab 100644 --- a/src/features/context-injector/collector.ts +++ b/src/features/context-injector/collector.ts @@ -14,6 +14,8 @@ const PRIORITY_ORDER: Record = { const CONTEXT_SEPARATOR = "\n\n---\n\n" +let registrationCounter = 0 + export class ContextCollector { private sessions: Map> = new Map() @@ -30,7 +32,7 @@ export class ContextCollector { source: options.source, content: options.content, priority: options.priority ?? "normal", - timestamp: Date.now(), + registrationOrder: ++registrationCounter, metadata: options.metadata, } @@ -77,7 +79,7 @@ export class ContextCollector { return entries.sort((a, b) => { const priorityDiff = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority] if (priorityDiff !== 0) return priorityDiff - return a.timestamp - b.timestamp + return a.registrationOrder - b.registrationOrder }) } } diff --git a/src/features/context-injector/types.ts b/src/features/context-injector/types.ts index c203be981..23030d0e9 100644 --- a/src/features/context-injector/types.ts +++ b/src/features/context-injector/types.ts @@ -27,8 +27,8 @@ export interface ContextEntry { content: string /** Priority for ordering (default: normal) */ priority: ContextPriority - /** Timestamp when registered */ - timestamp: number + /** Monotonic order when registered */ + registrationOrder: number /** Optional metadata for debugging/logging */ metadata?: Record }