source.fact.ngo a coherence.ngo project

scripts/plan.js

raw ↗ · AGPL-3.0

#!/usr/bin/env node // plan.js — generates the interview plan (cells = domain x lens pairs) for one // model into its dataset repo, and seeds the manifest. import fs from "node:fs"; import path from "node:path"; import { loadDomains, loadLenses, parseArgs, nowIso, PROTOCOL_VERSION, modelSlug } from "./lib.js"; import { findModel } from "./models.js"; const { args } = parseArgs(process.argv.slice(2), { model: { takes: "value", default: null }, dataset: { takes: "value", default: null }, depth: { takes: "value", default: "standard" }, }); if (!args.model) { console.error("--model is required"); process.exit(2); } if (!args.dataset) { console.error("--dataset (dataset repo path) is required"); process.exit(2); } if (!["minimal", "standard", "deep"].includes(args.depth)) { console.error("--depth must be minimal|standard|deep"); process.exit(2); } const domains = loadDomains(); const lenses = loadLenses(); const lensById = Object.fromEntries(lenses.map((l) => [l.id, l])); const model = findModel(args.model); const cells = []; const push = (domain, lens) => cells.push({ cell_id: `${domain}-${lens}`, domain, lens, status: "pending" }); if (args.depth === "deep") { for (const d of domains) for (const l of lenses) if (l.id !== "self-model") push(d.id, l.id); } else if (args.depth === "standard") { domains.forEach((d, i) => { push(d.id, "principles"); push(d.id, "prospective"); if (d.retrospective_weight === "high") push(d.id, "retrospective"); if (i % 3 === 0) push(d.id, "controversy"); if (i % 3 === 1) push(d.id, "blindspots"); }); } else { domains.forEach((d, i) => { if (i % 3 !== 0) return; push(d.id, "principles"); push(d.id, "prospective"); }); } push("meta", "self-model"); fs.mkdirSync(args.dataset, { recursive: true }); // Don't clobber existing progress if re-run with the same depth. const planPath = path.join(args.dataset, "plan.yaml"); if (fs.existsSync(planPath)) { const existing = fs.readFileSync(planPath, "utf8"); const done = (existing.match(/status: (done|in_progress)/g) || []).length; const prevCells = (existing.match(/^ - cell_id:/gm) || []).length; if (prevCells === cells.length) { console.log(`plan.yaml already exists with ${prevCells} cells (${done} done/in-progress) — kept.`); } else { const backup = planPath + ".bak"; fs.renameSync(planPath, backup); console.log(`plan.yaml depth changed (was ${prevCells} cells) — old plan moved to ${backup}.`); } } const yaml = [ `# xray interview plan — generated by scripts/plan.js`, `model: ${args.model}`, `model_slug: ${modelSlug(args.model)}`, `depth: ${args.depth}`, `protocol_version: ${PROTOCOL_VERSION}`, `created: ${nowIso()}`, ``, `cells:`, ...cells.map((c) => [ ` - cell_id: ${c.cell_id}`, ` domain: ${c.domain}`, ` lens: ${c.lens}`, ` status: ${c.status}`, ` session: null`, ].join("\n")), ].join("\n") + "\n"; fs.writeFileSync(planPath, yaml, "utf8"); // Seed manifest if absent const manifestPath = path.join(args.dataset, "manifest.json"); if (!fs.existsSync(manifestPath)) { const manifest = { dataset: modelSlug(args.model), model: { id: args.model, family: model?.family ?? null, version: null, host: "cloudflare-workers-ai", quantization: model?.quant ?? null, context_window_tokens: model?.context ?? null, }, depth: args.depth, protocol_version: PROTOCOL_VERSION, record_schema: "https://fact.ngo/xray/schemas/record.schema.json", created: nowIso(), elicited_by: "xray.fact.ngo", license_note: "Model outputs archived under the terms of the model's license. Verify license terms of the model before redistribution.", }; fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf8"); } fs.mkdirSync(path.join(args.dataset, "sessions"), { recursive: true }); fs.mkdirSync(path.join(args.dataset, "records"), { recursive: true }); console.log(`plan written: ${planPath}`); console.log(`cells: ${cells.length} (depth=${args.depth}, domains=${domains.length})`); const byLens = {}; for (const c of cells) byLens[c.lens] = (byLens[c.lens] || 0) + 1; console.log("per lens:", Object.entries(byLens).map(([k, v]) => `${k}=${v}`).join(" "));