Files
brain/tools/enforce-verdict-ack.mjs
T
Дмитрий abf2060328 feat standby: штатный режим - флаг, управляющий хук, сброс, страж в 12 хуков
Сессионный флаг standby-mode + управляющий UserPromptSubmit-хук рукопожатия + SessionStart-сброс. Страж if standbyActive в 12 блокирующих хуках; рельсы floor/snapshot/verify-gate не тронуты.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 10:07:04 +03:00

41 lines
2.1 KiB
JavaScript

#!/usr/bin/env node
/** enforce-verdict-ack — Stop-хук. Если на ходе был surfaced-вердикт (pending-ack), а в ответе нет
* строки `вердикт:` — громкая претензия (маркер остаётся → нагнетает до подтверждения). При ack —
* чистит маркер. Fail-quiet через exitDisciplineDecision. (SP1) */
import { readStdin, parseEventJson, readTranscript, lastAssistantText, exitDisciplineDecision } from './enforce-hook-helpers.mjs';
import { parseVerdictAck } from './verdict-outcome-line.mjs';
import { readPendingAck, clearPendingAck } from './verdict-surface-store.mjs';
/** Чистая: решение по наличию pending-ack и факту подтверждения в тексте. */
export function decide({ pendingAck, assistantText }) {
if (!pendingAck || pendingAck.length === 0) return { block: false };
if (parseVerdictAck(assistantText)) return { block: false, acked: true };
return {
block: true,
message: [
`[enforce-verdict-ack] на ходе был показан вердикт (${pendingAck.join(', ')}), но ответ его не подтвердил.`,
'ПЕРВОЙ строкой следующего ответа: `вердикт: <outcome>` (повтори исход из баннера).',
].join('\n'),
};
}
async function main() {
const ev = parseEventJson(await readStdin());
const sid = ev.session_id || ev.sessionId || 'unknown';
{ const __h = await import('./enforce-hook-helpers.mjs'); if (__h.standbyActive(sid)) return __h.exitDecision({ block: false }); }
await exitDisciplineDecision(
() => {
const transcript = readTranscript(ev.transcript_path);
const assistantText = lastAssistantText(transcript);
const pendingAck = readPendingAck(sid);
const r = decide({ pendingAck, assistantText });
if (r.acked) clearPendingAck(sid);
return r;
},
{ label: 'enforce-verdict-ack' },
);
}
const isCli = process.argv[1] && process.argv[1].replace(/\\/g, '/').endsWith('/enforce-verdict-ack.mjs');
if (isCli) main();