Files
brain/tools/verdict-wait.mjs
T

44 lines
2.3 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* verdict-wait — read-only сторож видимости «всё в лоб». Ждёт ПО ЭТАПАМ, пока стадия снимка не
* «осядет» (status !== pending), с ранним возвратом: лёг за 30с → вернул за 30с; иначе таймаут НА
* ЭТАП (до 5 мин). Ничего не мутирует (только чтение снимка). fail-quiet.
* CLI: node verdict-wait.mjs <hash> <stage> [timeoutMs]. Запускать в фоне (run_in_background) —
* выход = доставка исхода стадии разработчику.
*/
import { readSnapshot } from './verdict-surface-store.mjs';
/** Стадия «осела» — есть запись и статус не pending (терминальный исход). */
export function isStageSettled(snapshotMap, stage) {
const r = snapshotMap && snapshotMap[stage];
return !!(r && r.status && r.status !== 'pending');
}
/** Человекочитаемая сводка по стадии — для доставки в лицо. */
export function formatWaitResult(snapshotMap, stage) {
const r = (snapshotMap && snapshotMap[stage]) || null;
if (!r) return `[verdict-wait] ${stage}: нет записи (этап не стартовал)`;
if (r.status === 'pending') return `[verdict-wait] ${stage}: ещё печётся (pending)`;
return `[verdict-wait] ${stage}: ${r.status}${r.reason ? `${r.reason}` : ''}`;
}
async function main() {
const [hash, stage, timeoutArg] = process.argv.slice(2);
const sid = process.env.CLAUDE_SESSION_ID || 'unknown';
const timeoutMs = Math.min(Number(timeoutArg) || 300000, 300000); // предел НА ЭТАП — до 5 мин
const stepMs = 2000;
let waited = 0;
for (;;) {
let snap = {};
try { snap = readSnapshot(sid, hash); } catch { snap = {}; }
if (isStageSettled(snap, stage)) { process.stdout.write(formatWaitResult(snap, stage) + '\n'); return; }
if (waited >= timeoutMs) { process.stdout.write(`[verdict-wait] ${stage}: таймаут ${timeoutMs}ms — этап не осел\n`); return; }
await new Promise((res) => setTimeout(res, stepMs));
waited += stepMs;
}
}
import { fileURLToPath } from 'node:url';
const isCli = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
if (isCli) main();