run-ledger.test.ts
1 import assert from 'node:assert/strict' 2 import { test } from 'node:test' 3 import { runWithTempDataDir } from '@/lib/server/test-utils/run-with-temp-data-dir' 4 5 test('buildRetrievalSummary preserves citation count and dedupes source ids', () => { 6 const output = runWithTempDataDir<{ 7 empty: unknown 8 summary: { citationCount: number; sourceIds: string[] } | null 9 }>(` 10 const ledgerMod = await import('./src/lib/server/runtime/run-ledger.ts') 11 const ledger = ledgerMod.default || ledgerMod 12 13 const summary = ledger.buildRetrievalSummary([ 14 { sourceId: 'source-a' }, 15 { sourceId: 'source-a' }, 16 { sourceId: 'source-b' }, 17 ]) 18 19 console.log(JSON.stringify({ 20 empty: ledger.buildRetrievalSummary([]), 21 summary, 22 })) 23 `, { prefix: 'swarmclaw-run-ledger-summary-' }) 24 25 assert.equal(output.empty, null) 26 assert.deepEqual(output.summary, { 27 citationCount: 3, 28 sourceIds: ['source-a', 'source-b'], 29 }) 30 }) 31 32 test('appendPersistedRunEvent stores citations and retrieval traces', () => { 33 const output = runWithTempDataDir<{ 34 eventCount: number 35 citationCount: number 36 selectorStatus: string | null 37 sourceIds: string[] 38 }>(` 39 const ledgerMod = await import('./src/lib/server/runtime/run-ledger.ts') 40 const storageMod = await import('./src/lib/server/storage.ts') 41 const ledger = ledgerMod.default || ledgerMod 42 const storage = storageMod.default || storageMod 43 44 ledger.persistRun({ 45 id: 'run-grounded', 46 sessionId: 'session-1', 47 source: 'chat', 48 internal: false, 49 mode: 'followup', 50 status: 'completed', 51 messagePreview: 'grounded response', 52 queuedAt: 1, 53 retrievalSummary: null, 54 }) 55 56 ledger.appendPersistedRunEvent({ 57 runId: 'run-grounded', 58 sessionId: 'session-1', 59 phase: 'status', 60 status: 'completed', 61 citations: [{ 62 sourceId: 'source-a', 63 sourceTitle: 'Gateway Runbook', 64 sourceKind: 'manual', 65 sourceUrl: null, 66 sourceLabel: null, 67 chunkId: 'chunk-1', 68 chunkIndex: 0, 69 chunkCount: 1, 70 charStart: 0, 71 charEnd: 42, 72 sectionLabel: null, 73 snippet: 'Use blue green deployment for gateway changes.', 74 whyMatched: 'Matched query terms: gateway, deployment', 75 score: 0.91, 76 }], 77 retrievalTrace: { 78 query: 'gateway deployment', 79 scope: 'source_knowledge', 80 hits: [{ 81 sourceId: 'source-a', 82 sourceTitle: 'Gateway Runbook', 83 sourceKind: 'manual', 84 sourceUrl: null, 85 sourceLabel: null, 86 chunkId: 'chunk-1', 87 chunkIndex: 0, 88 chunkCount: 1, 89 charStart: 0, 90 charEnd: 42, 91 sectionLabel: null, 92 snippet: 'Use blue green deployment for gateway changes.', 93 whyMatched: 'Matched query terms: gateway, deployment', 94 score: 0.91, 95 }], 96 retrievedAt: 123, 97 selectorStatus: 'selected', 98 }, 99 event: { 100 t: 'md', 101 text: '{"run":{"status":"completed"}}', 102 }, 103 }) 104 105 const events = Object.values(storage.loadRuntimeRunEvents()) 106 const stored = events[0] 107 108 console.log(JSON.stringify({ 109 eventCount: events.length, 110 citationCount: Array.isArray(stored?.citations) ? stored.citations.length : 0, 111 selectorStatus: stored?.retrievalTrace?.selectorStatus || null, 112 sourceIds: Array.isArray(stored?.citations) ? stored.citations.map((citation) => citation.sourceId) : [], 113 })) 114 `, { prefix: 'swarmclaw-run-ledger-events-' }) 115 116 assert.equal(output.eventCount, 1) 117 assert.equal(output.citationCount, 1) 118 assert.equal(output.selectorStatus, 'selected') 119 assert.deepEqual(output.sourceIds, ['source-a']) 120 })