#!/usr/bin/env node
/**
 * Rule #1 — Mandatory re-classification injection.
 *
 * UserPromptSubmit hook. Reads router-state-<session>.json (output of the
 * existing router-prehook), reads rationalization flags from previous turns,
 * and injects an `additionalContext` block into the conversation.
 *
 * The block:
 *   1. Reminds: first line must be `coverage: <channel>:<id>`
 *   2. Lists recommended node/skill from classifier
 *   3. Surfaces previous-turn rationalization flags (if any)
 *
 * NEVER blocks the prompt — failed injection just means no reminder appears.
 *
 * Spec: docs/superpowers/specs/2026-05-25-enforce-hard-rules-design.md
 */

import {
  readStdin,
  parseEventJson,
  readRouterState,
  readRationalizationFlags,
  findOverride,
  loadOverrideVocab,
} from './enforce-hook-helpers.mjs';

const SUPPRESS_RULE = 'classifier-mismatch';

export function buildReminder({ classification, recentFlags, override }) {
  const lines = ['## §17 Coverage / Discipline Reminder', ''];
  if (override) {
    lines.push(`Override phrase detected: "${override.phrase}". The following rules are suppressed for THIS prompt only:`);
    lines.push(`  ${override.suppresses.join(', ')}`);
    lines.push('');
  }
  lines.push('**First line of your response MUST be:**');
  lines.push('  `coverage: <channel>:<id>`');
  lines.push('Channels: skill, node, chain, hook, agent, direct.');
  lines.push('');
  if (classification) {
    lines.push(`**Classifier output:** task_type=${classification.task_type || 'unknown'}, confidence=${classification.confidence ?? 'n/a'}`);
    if (classification.recommended_node) {
      lines.push(`**Recommended node:** ${classification.recommended_node}`);
    }
    if (classification.recommended_chain) {
      lines.push(`**Recommended chain:** ${classification.recommended_chain}`);
    }
    if (classification.task_type && /^(feature|bugfix|refactor|cleanup)$/i.test(classification.task_type)) {
      lines.push(`**Plan required:** task type ${classification.task_type} requires either Skill(superpowers:writing-plans) invocation OR an existing plan file referenced before first production-code edit.`);
    }
    lines.push('');
  }
  if (Array.isArray(recentFlags) && recentFlags.length > 0) {
    const recent = recentFlags.slice(-3);
    lines.push('**Previous turn flagged:**');
    for (const f of recent) lines.push(`  - ${f.kind}: ${typeof f.evidence === 'string' ? f.evidence.slice(0, 120) : ''}`);
    lines.push('Adjust behaviour accordingly.');
    lines.push('');
  }
  return lines.join('\n');
}

async function main() {
  try {
    const raw = await readStdin();
    const event = parseEventJson(raw);
    const sessionId = event.session_id;
    const userPrompt = event.prompt || '';

    // Override does NOT suppress this injection (it just notes the override).
    const vocab = loadOverrideVocab();
    let override = null;
    for (const p of (vocab.phrases || [])) {
      if (!p.phrase) continue;
      if (userPrompt.toLowerCase().includes(p.phrase.toLowerCase())) { override = p; break; }
    }

    // Wait up to ~600ms for router-prehook to write state.
    let state = readRouterState(sessionId);
    if (!state) {
      const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
      for (let i = 0; i < 3 && !state; i++) {
        await sleep(200);
        state = readRouterState(sessionId);
      }
    }
    const classification = state && state.classification ? {
      task_type: state.classification.task_type,
      confidence: state.classification.confidence,
      recommended_node: state.classification.recommended_node || state.classification.recommendedNode,
      recommended_chain: state.classification.recommended_chain || state.classification.recommendedChain,
    } : null;

    const flags = readRationalizationFlags(sessionId);

    const reminder = buildReminder({ classification, recentFlags: flags, override });

    process.stdout.write(JSON.stringify({
      hookSpecificOutput: {
        hookEventName: 'UserPromptSubmit',
        additionalContext: reminder,
      },
    }));
    process.exit(0);
  } catch {
    try { process.stdout.write('{}'); } catch { /* ignore */ }
    process.exit(0);
  }
}

const isCli = process.argv[1] && process.argv[1].replace(/\\/g, '/').endsWith('/enforce-prompt-injection.mjs');
if (isCli) main();
