Files
jason.woltje 6bad02612a lead: commit dewey's untracked evidence (721 files: queue-124-review queue-143 queue-149 queue-165-review queue-170 queue-175 queue-177 queue-184 queue-191)
Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
2026-11-02 15:05:14 -06:00

114 lines
5.4 KiB
Plaintext

// REQ-LIMIT-4: hostile transcripts are a best reading, never proof of usage.
// Linux dirfds anchor every lookup; no caller-provided symlink is followed.
import { constants, openSync, closeSync, fstatSync, readSync, opendirSync } from 'node:fs';
import { isAbsolute } from 'node:path';
export const interfaceVersion = 1;
const MAX_BYTES = 8 * 1024 * 1024;
const MAX_LINE = 1024 * 1024;
const MAX_ENTRIES = 512;
const MAX_RECORDS = 20000;
const ID = /^[A-Za-z0-9_-]{1,128}$/;
const NAME = /^[A-Za-z0-9_.-]{1,240}$/;
const DIR = constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW;
const FILE = constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK;
const refuse = code => { throw Object.assign(new Error(code), { code }); };
const at = (fd, name) => `/proc/self/fd/${fd}/${name}`;
function rootFd(root) {
if (typeof root !== 'string' || !isAbsolute(root) || root.split('/').includes('..')) refuse('transcript-path');
let fd = openSync('/', DIR);
try {
for (const part of root.split('/').filter(Boolean)) {
const next = openSync(at(fd, part), DIR);
closeSync(fd); fd = next;
}
return fd;
} catch (e) { closeSync(fd); throw e; }
}
function readFile(parent, name, budget) {
const fd = openSync(at(parent, name), FILE);
try {
const before = fstatSync(fd);
if (!before.isFile() || before.nlink !== 1) refuse('transcript-path');
if (before.size > MAX_BYTES - budget.bytes) refuse('transcript-size');
const parts = [];
let total = 0;
const buffer = Buffer.alloc(65536);
for (;;) {
const n = readSync(fd, buffer, 0, Math.min(buffer.length, MAX_BYTES - budget.bytes + 1), null);
if (!n) break;
total += n; budget.bytes += n;
if (budget.bytes > MAX_BYTES) refuse('transcript-size');
parts.push(Buffer.from(buffer.subarray(0, n)));
}
const after = fstatSync(fd);
if (before.size !== after.size || total !== after.size || before.mtimeMs !== after.mtimeMs ||
before.ctimeMs !== after.ctimeMs) refuse('transcript-changed');
return Buffer.concat(parts);
} finally { closeSync(fd); }
}
function counters(usage, harness) {
if (!usage || typeof usage !== 'object' || Array.isArray(usage)) refuse('transcript-usage');
const fields = harness === 'pi' ? ['input', 'output', 'cacheWrite', 'cacheRead'] :
['input_tokens', 'output_tokens', 'cache_creation_input_tokens', 'cache_read_input_tokens'];
const values = fields.map((key, i) => harness === 'claude-code' && i > 1 ? (usage[key] ?? 0) : usage[key]);
if (values.some(n => !Number.isSafeInteger(n) || n < 0)) refuse('transcript-usage');
return Object.fromEntries(['input', 'output', 'cacheWrite', 'cacheRead'].map((key, i) => [key, values[i]]));
}
function parse(bytes, harness, file, entries, budget) {
let text;
try { text = new TextDecoder('utf-8', { fatal: true }).decode(bytes); }
catch { refuse('transcript-parse'); }
if (text && !text.endsWith('\n')) refuse('transcript-parse');
for (const line of text.split('\n')) {
if (!line.trim()) continue;
if (Buffer.byteLength(line) > MAX_LINE) refuse('transcript-line');
if (++budget.records > MAX_RECORDS) refuse('transcript-records');
let record;
try { record = JSON.parse(line); } catch { refuse('transcript-parse'); }
if (!record || typeof record !== 'object' || Array.isArray(record)) refuse('transcript-parse');
if (harness === 'pi' ? record.type !== 'message' || record.message?.role !== 'assistant' : record.type !== 'assistant') continue;
const id = harness === 'pi' ? record.id : record.message?.id;
if (typeof id !== 'string' || !ID.test(id)) refuse('transcript-usage');
const value = counters(record.message?.usage, harness);
const key = `${file}:${id}`;
if (Object.hasOwn(entries, key) && JSON.stringify(entries[key]) !== JSON.stringify(value)) refuse('transcript-usage');
entries[key] = value;
}
}
function walk(fd, harness, depth, prefix, entries, budget) {
const directory = opendirSync(`/proc/self/fd/${fd}`);
try {
let entry;
while ((entry = directory.readSync())) {
if (++budget.entries > MAX_ENTRIES) refuse('transcript-entries');
if (!NAME.test(entry.name) || entry.name === '.' || entry.name === '..') refuse('transcript-path');
if (harness === 'claude-code' && depth === 0) {
// Only the standard project directory / session.jsonl shape is admitted.
if (entry.isFile()) continue;
const child = openSync(at(fd, entry.name), DIR);
try { walk(child, harness, 1, entry.name + '/', entries, budget); }
finally { closeSync(child); }
} else if (entry.name.endsWith('.jsonl')) {
parse(readFile(fd, entry.name, budget), harness, prefix + entry.name, entries, budget);
}
}
} finally { directory.closeSync(); }
}
export async function readTurn({ harness, root }) {
let fd;
try {
if (!['pi', 'claude-code'].includes(harness)) refuse('transcript-harness');
fd = rootFd(root);
const entries = Object.create(null);
walk(fd, harness, 0, '', entries, { bytes: 0, entries: 0, records: 0 });
return { status: 'known', entries };
} catch (e) {
// A new run can have no transcript directory before its first turn.
if (e.code === 'ENOENT' && fd === undefined) return { status: 'known', entries: {} };
const code = typeof e.code === 'string' && e.code.startsWith('transcript-') ? e.code : 'transcript-path';
return { status: 'unknown', code };
} finally { if (fd !== undefined) closeSync(fd); }
}