import test from 'node:test'; import assert from 'node:assert/strict'; import { mkdtempSync, mkdirSync, writeFileSync, rmSync, symlinkSync, linkSync } from 'node:fs'; import fs, { appendFileSync } from 'node:fs'; import { syncBuiltinESMExports } from 'node:module'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; import { readTurn } from '../usage-source/transcript/index.mjs'; function fixture(t, harness = 'pi') { const root = mkdtempSync(join(tmpdir(), 'usage-source-')); t.after(() => rmSync(root, { recursive: true, force: true })); const dir = harness === 'pi' ? root : join(root, 'project'); mkdirSync(dir, { recursive: true }); const file = join(dir, 'session.jsonl'); const pi = { type: 'message', id: 'assistant1', message: { role: 'assistant', usage: { input: 12, output: 3, cacheWrite: 4, cacheRead: 5 } } }; const claude = { type: 'assistant', uuid: 'record1', message: { id: 'assistant1', role: 'assistant', usage: { input_tokens: 12, output_tokens: 3, cache_creation_input_tokens: 4, cache_read_input_tokens: 5 } } }; const entry = harness === 'pi' ? pi : claude; const put = value => writeFileSync(file, JSON.stringify(value) + '\n'); put(entry); return { root, file, entry, put, read: () => readTurn({ harness, root }) }; } for (const harness of ['pi', 'claude-code']) test(`REQ-LIMIT-4 ${harness}: reports all token kinds and deduplicates assistant ids`, async t => { const f = fixture(t, harness); writeFileSync(f.file, [f.entry, f.entry].map(JSON.stringify).join('\n') + '\n'); const result = await f.read(); assert.equal(result.status, 'known'); assert.deepEqual(Object.values(result.entries), [{ input: 12, output: 3, cacheWrite: 4, cacheRead: 5 }]); }); for (const harness of ['pi', 'claude-code']) for (const [name, change, code] of [ ['cut line', f => writeFileSync(f.file, '{"type":'), 'transcript-parse'], ['invalid UTF-8', f => writeFileSync(f.file, Buffer.concat([Buffer.from('{"type":"user","text":"'), Buffer.from([0xff]), Buffer.from('"}\n')])), 'transcript-parse'], ['missing input', f => { delete f.entry.message.usage[f.entry.type === 'assistant' ? 'input_tokens' : 'input']; f.put(f.entry); }, 'transcript-usage'], ['negative count', f => { f.entry.message.usage[f.entry.type === 'assistant' ? 'output_tokens' : 'output'] = -1; f.put(f.entry); }, 'transcript-usage'], ['fractional count', f => { f.entry.message.usage[f.entry.type === 'assistant' ? 'output_tokens' : 'output'] = 0.5; f.put(f.entry); }, 'transcript-usage'], ['unsafe integer', f => { f.entry.message.usage[f.entry.type === 'assistant' ? 'output_tokens' : 'output'] = Number.MAX_SAFE_INTEGER + 1; f.put(f.entry); }, 'transcript-usage'], ['file size', f => writeFileSync(f.file, ' '.repeat(8 * 1024 * 1024 + 1)), 'transcript-size'], ['line size', f => writeFileSync(f.file, JSON.stringify({ type: 'user', text: 'x'.repeat(1024 * 1024) }) + '\n'), 'transcript-line'], ['symlink file', f => { const other = join(f.root, 'other'); writeFileSync(other, JSON.stringify(f.entry) + '\n'); rmSync(f.file); symlinkSync(other, f.file); }, 'transcript-path'], ['hardlink file', f => linkSync(f.file, join(f.root, 'linked')), 'transcript-path'], ]) test(`REQ-LIMIT-4 ${harness} ${name} is unknown, never zero or content`, async t => { const f = fixture(t, harness); change(f); assert.deepEqual(await f.read(), { status: 'unknown', code }); }); for (const harness of ['pi', 'claude-code']) test(`REQ-LIMIT-4 ${harness} a symlink directory anywhere in the root refuses`, async t => { const f = fixture(t, harness), alias = join(f.root, 'alias'); symlinkSync(f.root, alias); assert.deepEqual(await readTurn({ harness, root: alias }), { status: 'unknown', code: 'transcript-path' }); }); test('REQ-LIMIT-4 bounded directory entries refuse before scanning an arbitrary tree', async t => { const f = fixture(t); for (let n = 0; n < 513; n++) writeFileSync(join(f.root, `ignored-${n}`), ''); assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-entries' }); }); test('REQ-LIMIT-4 conflicting repeated usage refuses rather than double counting', async t => { const f = fixture(t), second = structuredClone(f.entry); second.message.usage.input++; writeFileSync(f.file, [f.entry, second].map(JSON.stringify).join('\n') + '\n'); assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-usage' }); }); test('REQ-LIMIT-4 oversized metadata refuses before reading any transcript bytes', async t => { const f = fixture(t); writeFileSync(f.file, 'x'.repeat(8 * 1024 * 1024 + 1)); let reads = 0; const original = fs.readSync; fs.readSync = (...args) => { reads++; return original(...args); }; syncBuiltinESMExports(); try { assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-size' }); assert.equal(reads, 0); } finally { fs.readSync = original; syncBuiltinESMExports(); } }); test('REQ-LIMIT-4 a file growing after fstat cannot exceed the streaming byte budget', async t => { const f = fixture(t); let grew = false; const original = fs.readSync; fs.readSync = (...args) => { if (!grew) { grew = true; appendFileSync(f.file, 'x'.repeat(8 * 1024 * 1024)); } return original(...args); }; syncBuiltinESMExports(); try { assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-size' }); } finally { fs.readSync = original; syncBuiltinESMExports(); } }); test('REQ-LIMIT-4 a same-size edit during a read is unknown rather than a stable snapshot', async t => { const f = fixture(t); const original = fs.readSync; let edited = false; fs.readSync = (...args) => { if (!edited) { edited = true; const bytes = fs.readFileSync(f.file); fs.writeFileSync(f.file, bytes); } return original(...args); }; syncBuiltinESMExports(); try { assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-changed' }); } finally { fs.readSync = original; syncBuiltinESMExports(); } }); test('REQ-LIMIT-4 record count is bounded even when each record is tiny', async t => { const f = fixture(t); writeFileSync(f.file, '{"type":"user"}\n'.repeat(20001)); assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-records' }); }); test('REQ-LIMIT-4 missing assistant usage, malformed JSON and conflicting identities are unknown', async t => { const f = fixture(t); for (const value of [{ type: 'message', id: 'a', message: { role: 'assistant' } }, { ...f.entry, id: '../bad' }]) { f.put(value); assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-usage' }); } writeFileSync(f.file, 'not-json\n'); assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-parse' }); }); test('REQ-LIMIT-4 caller roots, unsupported harnesses and non-object JSON never become zero usage', async t => { assert.deepEqual(await readTurn({ harness: 'pi', root: 'relative' }), { status: 'unknown', code: 'transcript-path' }); const f = fixture(t); assert.deepEqual(await readTurn({ harness: 'other', root: f.root }), { status: 'unknown', code: 'transcript-harness' }); for (const value of [null, [], 7]) { f.put(value); assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-parse' }); } }); test('REQ-LIMIT-4 even a complete JSON record with no final newline is an unknown cut line', async t => { const f = fixture(t); writeFileSync(f.file, JSON.stringify(f.entry)); assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-parse' }); }); test('REQ-LIMIT-4 final file opens are nonblocking before hostile file type is known', async t => { const f = fixture(t), original = fs.openSync; const flags = []; fs.openSync = (path, mode, ...args) => { if (String(path).endsWith('/session.jsonl')) flags.push(mode); return original(path, mode, ...args); }; syncBuiltinESMExports(); try { assert.equal((await f.read()).status, 'known'); assert.equal(flags.length, 1); assert.ok(flags[0] & fs.constants.O_NONBLOCK); } finally { fs.openSync = original; syncBuiltinESMExports(); } }); test('REQ-LIMIT-4 invalid transcript entry names refuse before file lookup', async t => { const f = fixture(t); writeFileSync(join(f.root, 'bad name.jsonl'), JSON.stringify(f.entry) + '\n'); assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-path' }); }); // Claude's project-directory descent is separate from root and session-file opens. test('REQ-LIMIT-4 claude-code refuses a symlinked project directory', async t => { const f = fixture(t, 'claude-code'); const project = join(f.root, 'project'); const target = join(f.root, '..', 'project-target-' + f.root.split('/').at(-1)); mkdirSync(target); t.after(() => rmSync(target, { recursive: true, force: true })); writeFileSync(join(target, 'session.jsonl'), JSON.stringify(f.entry) + '\n'); rmSync(project, { recursive: true }); symlinkSync(target, project); assert.deepEqual(await f.read(), { status: 'unknown', code: 'transcript-path' }); });