Files
portal/tools/verdict-surface-store.mjs
T

48 lines
1.8 KiB
JavaScript

#!/usr/bin/env node
/** verdict-surface-store — рантайм-хранилище строк исхода (Фикс 1). fs инъектируется. best-effort. */
import fsDefault from 'node:fs';
import { join, dirname } from 'node:path';
import { homedir } from 'node:os';
export function surfacePath(sessionId, dir) {
const base = dir || join(homedir(), '.claude', 'runtime');
return join(base, `verdict-surface-${sessionId || 'unknown'}.jsonl`);
}
export function appendVerdictOutcome({ sessionId, line, nowMs = null, fsImpl = fsDefault, dir } = {}) {
if (typeof line !== 'string' || !line.trim()) return false;
try {
const p = surfacePath(sessionId, dir);
fsImpl.mkdirSync(dirname(p), { recursive: true });
fsImpl.appendFileSync(p, JSON.stringify({ line, at: nowMs, surfaced: false }) + '\n');
return true;
} catch { return false; }
}
export function readUnsurfaced({ sessionId, fsImpl = fsDefault, dir } = {}) {
try {
const p = surfacePath(sessionId, dir);
if (!fsImpl.existsSync(p)) return [];
const out = [];
for (const l of fsImpl.readFileSync(p, 'utf-8').split(/\r?\n/)) {
if (!l.trim()) continue;
let r; try { r = JSON.parse(l); } catch { continue; }
if (r && typeof r.line === 'string' && r.surfaced !== true) out.push(r.line);
}
return out;
} catch { return []; }
}
export function markAllSurfaced({ sessionId, fsImpl = fsDefault, dir } = {}) {
try {
const p = surfacePath(sessionId, dir);
if (!fsImpl.existsSync(p)) return false;
const lines = fsImpl.readFileSync(p, 'utf-8').split(/\r?\n/).filter(Boolean);
const rewritten = lines.map((l) => {
try { const r = JSON.parse(l); r.surfaced = true; return JSON.stringify(r); } catch { return l; }
}).join('\n');
fsImpl.writeFileSync(p, rewritten ? rewritten + '\n' : '');
return true;
} catch { return false; }
}