Measure the model-visible consultation payload on three public charts, draft per-domain cards, and record the Narayana/pratyantar projection gap as BUG-1054. No runtime behavior change.
108 lines
4.0 KiB
TypeScript
108 lines
4.0 KiB
TypeScript
/**
|
|
* Read-only projection of a consultation workflow payload into the text the
|
|
* answer model sees. Does not modify frontend runtime files.
|
|
*
|
|
* The single-domain wrap matches consultation-tools.ts toModelDomainPlanContext
|
|
* when consultations.length === 1 and omittedDomains.length === 0:
|
|
* return { ...consultations[0], ...plan, consultations };
|
|
*/
|
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
import { createConsultationPlan } from "../../frontend/src/lib/consultation-plan.ts";
|
|
import { consultationMethodologyForDomains } from "../../frontend/src/lib/consultation-methodology.ts";
|
|
import type { ConsultationDomain } from "../../frontend/src/lib/consultation-domain-registry.ts";
|
|
import {
|
|
consultationWorkflowResponseSchema,
|
|
toAgentConsultationContext,
|
|
toModelOutput,
|
|
} from "../../frontend/src/mastra/consultation-workflow.ts";
|
|
|
|
type JsonRecord = Record<string, unknown>;
|
|
|
|
function readJson(path: string): JsonRecord {
|
|
return JSON.parse(readFileSync(path, "utf8")) as JsonRecord;
|
|
}
|
|
|
|
function planFields(domain: ConsultationDomain, question: string) {
|
|
const plan = createConsultationPlan({
|
|
userIntent: question,
|
|
theme: domain,
|
|
consultationMode: "verified_chart",
|
|
});
|
|
return {
|
|
plan_version: plan.plan_version,
|
|
depth: plan.depth,
|
|
requested_domains: plan.requestedDomains,
|
|
timing_horizon: plan.timingHorizon,
|
|
precision_boundary: plan.precisionBoundary,
|
|
required_evidence_categories: plan.requiredEvidenceCategories,
|
|
birthTimeMode: plan.birthTimeMode,
|
|
};
|
|
}
|
|
|
|
function projectOne(workflow: JsonRecord, domain: ConsultationDomain, question: string) {
|
|
const parsed = consultationWorkflowResponseSchema.safeParse(workflow);
|
|
const agentContext = toAgentConsultationContext(parsed.success ? parsed.data : workflow);
|
|
const consultationPlan = createConsultationPlan({
|
|
userIntent: question,
|
|
theme: domain,
|
|
consultationMode: "verified_chart",
|
|
});
|
|
const modelOutput = toModelOutput(agentContext, consultationPlan);
|
|
const consultation = { domain, ...modelOutput };
|
|
const methodology = consultationMethodologyForDomains([domain]);
|
|
const plan = {
|
|
success: agentContext.success === true,
|
|
domains: [domain],
|
|
omitted_domains: [] as ConsultationDomain[],
|
|
...(methodology ? { methodology } : {}),
|
|
};
|
|
const modelContext = { ...consultation, ...plan, consultations: [consultation] };
|
|
return {
|
|
schema_ok: parsed.success,
|
|
schema_error: parsed.success ? null : parsed.error.issues.slice(0, 8).map((issue) => ({
|
|
path: issue.path.join("."),
|
|
code: issue.code,
|
|
})),
|
|
methodology_sections: methodology?.sections.length ?? 0,
|
|
methodology_chars: methodology
|
|
? JSON.stringify(methodology).length
|
|
: 0,
|
|
model_context: modelContext,
|
|
};
|
|
}
|
|
|
|
const [mode, ...rest] = process.argv.slice(2);
|
|
|
|
if (mode === "plans") {
|
|
const spec = readJson(rest[0]);
|
|
const questions = spec.questions as Array<{ id: string; domain: ConsultationDomain; question: string }>;
|
|
const plans: JsonRecord = {};
|
|
for (const item of questions) {
|
|
plans[item.id] = planFields(item.domain, item.question);
|
|
}
|
|
writeFileSync(rest[1], JSON.stringify(plans));
|
|
} else if (mode === "project") {
|
|
const jobs = readJson(rest[0]) as {
|
|
items: Array<{ id: string; domain: ConsultationDomain; question: string; workflow_path: string; out_path: string }>;
|
|
};
|
|
const summary: JsonRecord[] = [];
|
|
for (const item of jobs.items) {
|
|
const workflow = readJson(item.workflow_path);
|
|
const projected = projectOne(workflow, item.domain, item.question);
|
|
const text = JSON.stringify(projected.model_context);
|
|
writeFileSync(item.out_path, text);
|
|
summary.push({
|
|
id: item.id,
|
|
schema_ok: projected.schema_ok,
|
|
schema_error: projected.schema_error,
|
|
methodology_sections: projected.methodology_sections,
|
|
methodology_chars: projected.methodology_chars,
|
|
model_chars: text.length,
|
|
});
|
|
}
|
|
writeFileSync(rest[1], JSON.stringify(summary));
|
|
} else {
|
|
process.stderr.write("usage: plans <spec.json> <out.json> | project <jobs.json> <summary.json>\n");
|
|
process.exit(2);
|
|
}
|