Files
brain/tools/enforce-self-debrief-detector.mjs
T

60 lines
2.1 KiB
JavaScript

/**
* PreToolUse(Edit|Write|MultiEdit|Bash) wrapper for tools/self-debrief-detector.mjs.
* Router-gate v4.1 spec §3.12 (NEW).
*
* Reads last controller text from transcript; if it matches self-debrief patterns
* (я заметил паттерн / generalisable lesson / etc.) AND no self-retrospect or
* brain-retro Skill in recent turns — block.
*
* Fail-CLOSE on internal error.
*/
import { fileURLToPath } from 'url';
import {
readStdin,
parseEventJson,
readTranscript,
exitDecision,
} from './enforce-hook-helpers.mjs';
import { detectSelfDebrief } from './self-debrief-detector.mjs';
/** Extract last assistant (controller) text from transcript. */
export function lastControllerText(transcript) {
const recs = transcript || [];
for (let i = recs.length - 1; i >= 0; i--) {
const r = recs[i];
if (r && r.type === 'text' && r.role === 'assistant') return String(r.text || '');
if (r && r.role === 'assistant' && typeof r.content === 'string') return r.content;
}
return '';
}
export function decide({ controllerText, transcript }) {
const r = detectSelfDebrief(controllerText, transcript || []);
if (r.action === 'hard_block_next_mutating') {
return { block: true, reason: r.reason };
}
return { block: false, reason: null };
}
async function main() {
try {
const raw = await readStdin();
const event = parseEventJson(raw);
const mutating = ['Edit', 'Write', 'MultiEdit', 'Bash'];
if (!mutating.includes(event.tool_name)) return exitDecision({ block: false });
const transcript = readTranscript(event.transcript_path);
const controllerText = lastControllerText(transcript);
const r = decide({ controllerText, transcript });
if (r.block) {
return exitDecision({ block: true, message: `[self-debrief-detector] ${r.reason}` });
}
return exitDecision({ block: false });
} catch {
return exitDecision({ block: true, message: '[self-debrief-detector] внутренняя ошибка — fail-CLOSE' });
}
}
const isCli = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
if (isCli) main();