#!/usr/bin/env node
// Hook: post-compact-flush.mjs
// Event: PostCompact (Claude Code v2.1.105+)
// Purpose: Re-inject .session-state.local.json after compaction so
//          /ultracontinue and `/ultraexecute-local --resume` see fresh
//          session-state and the model has Handover 7 context immediately
//          after a context-compaction event.
//
// Read-only — never writes. Always exits 0; never blocks compaction.
//
// Behavior:
//   1. Auto-discover the most-recently-modified
//      <cwd>/.claude/projects/*/.session-state.local.json
//   2. Validate it via lib/validators/session-state-validator.mjs
//   3. Emit additionalContext containing project + next_session_label +
//      status so the next assistant turn has resume context loaded.
//
// Notes:
//   - Uses only node:fs sync APIs that have existed since Node 12 (no
//     glob dependency — that requires Node 22).
//   - Silent no-op if no state file is discoverable, or if the file is
//     malformed. Compaction must not be blocked under any circumstance.

import { readdirSync, statSync } from 'node:fs';
import { join } from 'node:path';
import { validateSessionState } from '../../lib/validators/session-state-validator.mjs';

function findActiveStateFile() {
  // Auto-discover: most recently modified .session-state.local.json
  // under <cwd>/.claude/projects/*/. Returns absolute path or null.
  const projectsDir = '.claude/projects';
  let entries;
  try { entries = readdirSync(projectsDir, { withFileTypes: true }); }
  catch { return null; } // .claude/projects/ absent → silent no-op
  let best = null;
  let bestMtime = 0;
  for (const ent of entries) {
    if (!ent.isDirectory()) continue;
    const candidate = join(projectsDir, ent.name, '.session-state.local.json');
    let st;
    try { st = statSync(candidate); }
    catch { continue; } // file missing in this project — skip
    if (st.mtimeMs > bestMtime) {
      bestMtime = st.mtimeMs;
      best = candidate;
    }
  }
  return best;
}

function main() {
  const stateFile = findActiveStateFile();
  if (!stateFile) {
    process.stdout.write(JSON.stringify({})); // silent no-op
    return;
  }
  const result = validateSessionState(stateFile);
  if (!result.valid || !result.parsed) {
    process.stdout.write(JSON.stringify({})); // silent fail
    return;
  }
  const p = result.parsed;
  const summary = `[Session resumed after compact]
project: ${p.project}
next_session: ${p.next_session_label}
status: ${p.status}`;
  process.stdout.write(JSON.stringify({
    additionalContext: summary.slice(0, 10000),
  }));
}

try { main(); }
catch { process.stdout.write(JSON.stringify({})); } // never block compaction
process.exit(0);
