#!/usr/bin/env node
// extract-vision stage 1b: reduce full corpus to the vision-dense slice the distiller reads.
// Keeps: first 40 entries (genesis era), ALL [Q] entries, substantive prompts (>=500 chars,
// not dispatch-shaped). Entries over 8000 chars are truncated, never dropped.
// Usage: node slice_corpus.mjs <corpus.md> <slice-out.md>
import fs from 'node:fs';

const [corpusPath, outPath] = process.argv.slice(2);
if (!corpusPath || !outPath) { console.error('usage: slice_corpus.mjs <corpus.md> <slice-out.md>'); process.exit(1); }

const raw = fs.readFileSync(corpusPath, 'utf8');
const parts = raw.split(/^### /m).slice(1).map(p => '### ' + p);
const entries = parts.map(p => {
  const header = p.slice(0, p.indexOf('\n'));
  const body = p.slice(p.indexOf('\n') + 1);
  return { header, body, isQ: header.includes('[Q]'), is1msg: header.includes('[1msg]'), len: body.length,
    ts: (header.match(/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2})/) || [, ''])[1] };
});
if (entries.length === 0) { console.error('no entries parsed — wrong file?'); process.exit(1); }

const sel = new Set();
entries.slice(0, 40).forEach((_, i) => sel.add(i));
entries.forEach((e, i) => { if (e.isQ) sel.add(i); });
entries.forEach((e, i) => { if (!e.is1msg && !e.isQ && e.len >= 500) sel.add(i); });

const picked = [...sel].sort((a, b) => a - b).map(i => entries[i]);
const out = picked.map(e => e.header + '\n' + (e.len > 8000 ? e.body.slice(0, 8000) + '\n[...truncated]' : e.body)).join('\n');
fs.writeFileSync(outPath, `# Vision-dense corpus slice (genesis + all [Q] + substantive prompts, chronological)\nSource: ${corpusPath}\n\n` + out);
console.log(JSON.stringify({ out: outPath, total: entries.length, picked: picked.length,
  qCount: picked.filter(e => e.isQ).length, sizeKB: Math.round(fs.statSync(outPath).size / 1024),
  firstTs: entries[0].ts, lastTs: entries[entries.length - 1].ts }));
