#!/usr/bin/env node
/**
 * mentor-journal (§6.3 SE-R6-4) — журнал переговоров наставник↔Claude. tamper-evident
 * на хеш-цепи (зеркало М1) — переиспользует action-journal-примитивы appendEntry/verifyChain.
 * Payload несёт task-id (✅O17 binding), круг, сторону, реплику, обоснование (ДР-6:
 * каждая сторона ОБЯЗАНА обоснование). Журнал ≠ М1 action-journal: своя семантика
 * записи + per-task счётчик кругов (R2-SE-d).
 * A4 (SE10): throw на пустом обосновании ОБЯЗАН ловиться вызывающим (onPlanWrite/контроллер,
 * C2-W3) try/catch → НЕ крах круга; пустое обоснование → требовать заново (переспрос).
 */
import { appendEntry, verifyChain } from './action-journal.mjs';

/** F-C7 (sharp-edges): стороны переговоров — closed-list (ДР-6 двусторонний спор). */
export const NEGOTIATION_SIDES = Object.freeze(['mentor', 'claude']);

/** Добавить запись переговоров. Обоснование обязательно (ДР-6) → throw при пустом.
 *  F-C2: taskId обязателен — запись вне per-task учёта (R2-SE-d) запрещена.
 *  F-C7: side только из NEGOTIATION_SIDES. */
export function appendNegotiation(entries, { taskId, round, side, utterance, justification }, { key, nowMs }) {
  if (!String(taskId || '').trim()) throw new Error('taskId обязателен — запись вне per-task учёта запрещена (F-C2, R2-SE-d)');
  if (!NEGOTIATION_SIDES.includes(side)) throw new Error(`side обязан быть из [${NEGOTIATION_SIDES.join('|')}] (F-C7)`);
  if (!String(justification || '').trim()) throw new Error('обоснование обязательно (ДР-6 симметрия)');
  const payload = {
    task_id: String(taskId || ''), round: Number(round) || 0,
    side: String(side || ''), utterance: String(utterance || ''), justification: String(justification),
  };
  return appendEntry(Array.isArray(entries) ? entries : [], payload, { key, nowMs });
}

/** Проверить цепь переговоров (зеркало verifyChain М1). */
export function verifyNegotiation(entries, headSig, { key }) {
  return verifyChain(entries, headSig, { key });
}

/** Максимальный номер круга для task-id (per-ЗАДАЧЕ счётчик, R2-SE-d). */
export function roundCount(entries, taskId) {
  let max = 0;
  for (const e of (Array.isArray(entries) ? entries : [])) {
    const p = e && e.payload;
    if (p && p.task_id === taskId && Number(p.round) > max) max = Number(p.round);
  }
  return max;
}
