#!/usr/bin/env node /** * Minimal startCase (initial decomposition) experiment harness. * * Loads .env.local, invokes startCase() through the real production path, * and prints a structured result for semantic evaluation. * * Usage: * node scripts/start-case-experiment-helper.cjs "" * node scripts/start-case-experiment-helper.cjs --file scenario.json * * Exit codes: * 0 — success (structured result printed to stdout) * 1 — execution failure or invalid input */ const dotenv = require("dotenv"); dotenv.config({ path: ".env.local" }); function assertRequiredEnv(name) { const value = process.env[name]; if (!value) { throw new Error( `Live experiment requires ${name}. Set it in .env.local.\n` + `Found: OLLAMA_BASE_URL=${process.env.OLLAMA_BASE_URL ?? "(missing)"}, ` + `OLLAMA_MODEL=${process.env.OLLAMA_MODEL ?? "(missing)"}` ); } return value; } function readScenarioInput(argv) { if (argv.includes("--file")) { const idx = argv.indexOf("--file"); if (idx + 1 >= argv.length) throw new Error("--file requires a path argument"); const fs = require("fs"); const path = argv[idx + 1]; return JSON.parse(fs.readFileSync(path, "utf-8")); } // Use all positional args as the scenario text (join with space) const startIdx = argv.findIndex(a => a !== "" && !a.startsWith("-") && a !== "--"); if (startIdx === -1 || startIdx >= argv.length) throw new Error("Usage: node scripts/start-case-experiment-helper.cjs \"\" [--file path.json]"); return { scenario: argv.slice(startIdx).join(" ") }; } async function runStartCaseExperiment(scenarioInput) { const baseUrl = assertRequiredEnv("OLLAMA_BASE_URL"); const model = assertRequiredEnv("OLLAMA_MODEL"); if (baseUrl === "http://localhost:11434" || baseUrl === "http://127.0.0.1:11434") { throw new Error( `Live experiment harness refuses to use localhost fallback. ` + `OLLAMA_BASE_URL=${baseUrl}. Configure a real host in .env.local.` ); } const { startCase } = await import("../../lib/graph/orchestrator.js"); const endToEndStartedAt = Date.now(); const result = await startCase(scenarioInput); const endToEndElapsedMs = Date.now() - endToEndStartedAt; return { success: result.success, summary: result.summary ?? null, situationGraphNodeCount: result.situationGraph?.nodes?.length ?? 0, situationGraphEdgeCount: result.situationGraph?.edges?.length ?? 0, selectedQuestion: result.selectedQuestion?.question ?? null, assessmentPhase: result.assessment?.phase ?? null, assessmentProgress: result.assessment?.progress ?? null, endToEndElapsedMs, diagnostics: result.diagnostics ?? null, error: result.success ? null : (result.error ?? "unknown"), statusCode: result.statusCode ?? (result.success ? 200 : 500), }; } (async () => { try { const scenarioInput = readScenarioInput(process.argv); const result = await runStartCaseExperiment(scenarioInput); console.log(JSON.stringify(result, null, 2)); process.exit(result.success ? 0 : 1); } catch (e) { console.error(`APPARATUS FAILURE: ${e.message}`); process.exit(1); } })();