#!/usr/bin/env node /** round-memory-store — дословные претензии судьи/наставника по (task_id, side) (Фикс 2a). best-effort. */ import fsDefault from 'node:fs'; import { join, dirname } from 'node:path'; import { homedir } from 'node:os'; export function roundMemoryPath(taskId, dir) { const base = dir || join(homedir(), '.claude', 'runtime'); const safe = String(taskId || 'unknown').replace(/[^a-zA-Z0-9_-]/g, '_'); return join(base, `round-memory-${safe}.jsonl`); } export function appendRoundObjection({ taskId, side, objectionVerbatim, nowMs = null, fsImpl = fsDefault, dir } = {}) { if (typeof objectionVerbatim !== 'string' || !objectionVerbatim.trim()) return false; try { const p = roundMemoryPath(taskId, dir); fsImpl.mkdirSync(dirname(p), { recursive: true }); fsImpl.appendFileSync(p, JSON.stringify({ side: String(side || ''), objection: objectionVerbatim, at: nowMs }) + '\n'); return true; } catch { return false; } } export function readRoundObjections({ taskId, side, fsImpl = fsDefault, dir } = {}) { try { const p = roundMemoryPath(taskId, dir); if (!fsImpl.existsSync(p)) return []; const out = []; for (const l of fsImpl.readFileSync(p, 'utf-8').split(/\r?\n/)) { if (!l.trim()) continue; let r; try { r = JSON.parse(l); } catch { continue; } if (r && r.side === side && typeof r.objection === 'string') out.push(r.objection); } return out; } catch { return []; } }