abf2060328
Сессионный флаг standby-mode + управляющий UserPromptSubmit-хук рукопожатия + SessionStart-сброс. Страж if standbyActive в 12 блокирующих хуках; рельсы floor/snapshot/verify-gate не тронуты. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
41 lines
2.1 KiB
JavaScript
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();
|