Files
brain/tools/enforce-verdict-surface.mjs
T

35 lines
1.7 KiB
JavaScript

#!/usr/bin/env node
/** enforce-verdict-surface — UserPromptSubmit. Дренит вердикты сессии → громкий баннер +
* императив подтверждения в additionalContext. Помечает pending-ack для Stop-стража.
* Fail-quiet: ошибка → пустой вывод, никогда не роняет ход. (SP1) */
import { drainVerdicts, markSurfaced } from './verdict-surface-store.mjs';
import { buildVerdictBanner } from './verdict-outcome-line.mjs';
const IMPERATIVE = 'ПЕРВОЙ строкой ответа подтверди: `вердикт: <outcome>` — иначе считается пропущенным.';
/** Чистая: список вердиктов → текст additionalContext, либо null если пусто. */
export function buildSurfaceOutput(verdicts) {
if (!Array.isArray(verdicts) || verdicts.length === 0) return null;
return verdicts.map(buildVerdictBanner).join('\n') + '\n' + IMPERATIVE;
}
async function readStdin() { let b = ''; for await (const c of process.stdin) b += c; return b; }
function emitNone() { process.stdout.write('{}'); }
async function main() {
try {
const ev = JSON.parse(await readStdin());
const sid = ev.session_id || ev.sessionId || 'unknown';
const verdicts = drainVerdicts(sid);
const out = buildSurfaceOutput(verdicts);
if (!out) return emitNone();
markSurfaced(sid, verdicts.map((v) => v.outcome));
process.stdout.write(JSON.stringify({
hookSpecificOutput: { hookEventName: 'UserPromptSubmit', additionalContext: out },
}));
} catch { emitNone(); }
}
const isCli = process.argv[1] && process.argv[1].replace(/\\/g, '/').endsWith('/enforce-verdict-surface.mjs');
if (isCli) main();