bhcto.com

content_round2.js

// Round 2 — SEO rewrite. Prompt = brief + round1/<slug>.md + seo/<slug>/intel.json.
// Writes round2/<slug>.md.  node content_round2.js [--slug <slug>] [--limit N]

const fs = require("fs");
const path = require("path");
const { parseBriefs } = require("./lib/briefs");
const { probeModel, runRound } = require("./lib/batch");
const P = require("./lib/prompts");
const { cleanArticle } = require("./lib/clean");

const R1 = path.join(__dirname, "round1");
const SEO = path.join(__dirname, "seo");
const OUT = path.join(__dirname, "round2");

function arg(name) {
  const i = process.argv.indexOf(`--${name}`);
  return i >= 0 ? process.argv[i + 1] : null;
}
function readMaybe(p) {
  try {
    return fs.readFileSync(p, "utf8");
  } catch {
    return null;
  }
}
function readJson(p) {
  const t = readMaybe(p);
  return t ? JSON.parse(t) : null;
}

async function main() {
  fs.mkdirSync(OUT, { recursive: true });
  const { standingRules, briefs } = parseBriefs();
  let items = briefs;
  if (arg("slug")) items = briefs.filter((b) => b.slug === arg("slug"));
  else if (arg("limit")) items = briefs.slice(0, Number(arg("limit")));

  // Only process briefs that have a round-1 draft.
  items = items.filter((b) => {
    const has = fs.existsSync(path.join(R1, `${b.slug}.md`));
    if (!has) console.warn(`  (skip ${b.slug}: no round1 draft)`);
    return has;
  });
  if (!items.length) {
    console.error("No round-1 drafts found. Run content_round1.js first.");
    process.exit(1);
  }

  const model = await probeModel();
  console.log(`Round 2: SEO-rewriting ${items.length} post(s) with ${model}`);

  const sys2 = P.round2System(standingRules);
  const results = await runRound(model, items, (brief) => {
    const round1md = readMaybe(path.join(R1, `${brief.slug}.md`));
    const intel = readJson(path.join(SEO, brief.slug, "intel.json"));
    return {
      system: sys2,
      userContent: P.round2User(brief, round1md, intel),
      max_tokens: 16000,
    };
  });

  let ok = 0;
  for (const b of items) {
    const r = results.get(b.slug);
    if (r && r.ok) {
      fs.writeFileSync(path.join(OUT, `${b.slug}.md`), cleanArticle(r.text));
      console.log(`  ✓ ${b.slug} (${r.model})`);
      ok++;
    } else {
      console.warn(`  ✗ ${b.slug} — ${r ? r.error || r.stop_reason : "no result"}`);
    }
  }
  console.log(`\nRound 2 done: ${ok}/${items.length} written to round2/. Next: content_round3.js.`);
}

main().catch((e) => {
  console.error("FATAL:", e.stack || e);
  process.exit(1);
});