#!/usr/bin/env node
/**
 * enforce-decomposition-detector — PreToolUse wrapper around the pure
 * decomposition-detector module (router-gate v4 §3.8 + v4.1 Direction 3).
 *
 * Catches features secretly decomposed into 3+ small prompts with overlapping
 * keywords WITHOUT a planning skill (writing-plans / brainstorming) ever
 * being invoked. v4.1 hard-blocks mutating tools when LLM-judge confirms.
 *
 * Stream H Task 5 — adds the wrapper. Pure detection + decision logic live
 * in decomposition-detector.mjs; this file is just the hook entry point.
 *
 * Settings.json registration deferred to Phase H-α/H-β batch step.
 */
import { detectDecompositionCandidate, decideDecomposition, V4_1_DECOMP_THRESHOLD } from './decomposition-detector.mjs';

/**
 * Pure decision composing detector + decider with a degraded-allow fallback
 * when the LLM verdict is missing (fail-open on the LLM layer — matches the
 * same pattern as llm-judge-per-tool).
 *
 * @param {object} args
 * @param {Array}  args.history      - prior prompt entries (oldest → newest)
 * @param {object} args.currentEntry - the current prompt entry
 * @param {string|null} args.llmVerdict - 'YES' | 'NO' | null
 * @param {object} [args.threshold]  - override the v4.1 thresholds
 * @returns {{action:'allow'|'soft_flag'|'hard_block_mutating', reason?:string, degraded?:boolean}}
 */
export function decide({ history, currentEntry, llmVerdict, threshold = V4_1_DECOMP_THRESHOLD }) {
  const candidate = detectDecompositionCandidate(history, currentEntry, threshold);
  if (!candidate.candidate) return { action: 'allow' };
  if (llmVerdict === null || llmVerdict === undefined) {
    // Threshold met but no LLM verdict available — degrade to soft surface
    // rather than hard-block (avoid the Stream G Task 8 self-lockout pattern
    // where a fail-CLOSE LLM hook bricks the session).
    return { action: 'soft_flag', reason: `${candidate.reason} (LLM judge unavailable — degraded allow)`, degraded: true };
  }
  return decideDecomposition(candidate, llmVerdict, threshold);
}

async function main() {
  // Minimal main(): without an active LLM-judge config + history-ledger reader,
  // this hook degrades to allow-with-soft-flag. Wiring full live behaviour is
  // Phase H-α/H-β tail work (LLM judge config from Stream D, history ledger
  // from observer Stop hook). Until then: exit 0 silently to avoid lockout.
  let input = '';
  for await (const chunk of process.stdin) input += chunk;
  // Intentionally no decode/parse — the hook is a no-op until history-ledger
  // + LLM-judge config are wired in the deferred batch.
  process.exit(0);
}

if (import.meta.url === `file://${process.argv[1].replace(/\\/g, '/')}` || (process.argv[1] || '').endsWith('enforce-decomposition-detector.mjs')) {
  main().catch(() => process.exit(0));
}
