Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions evals/fixtures/rubrics/operating-model-fit/clean.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"judge_response": {
"pass": true,
"routing": [
{
"unit_id": "cover",
"unit_type": "slide",
"treatment": "none",
"confidence": "high",
"reason": "The slide introduces the deck with one title."
},
{
"unit_id": "review-economics",
"unit_type": "slide",
"treatment": "relational",
"confidence": "high",
"reason": "The claim is a repeated-cost versus one-time-cost comparison."
},
{
"unit_id": "review-routing",
"unit_type": "slide",
"treatment": "operating-model",
"confidence": "high",
"reason": "The claim depends on policy-based routing."
},
{
"unit_id": "clinical-ide",
"unit_type": "slide",
"treatment": "simulated-surface",
"confidence": "high",
"reason": "The physician's interaction with evidence and hypotheses is the claim."
}
],
"findings": []
}
}
23 changes: 23 additions & 0 deletions evals/fixtures/rubrics/operating-model-fit/fire.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"judge_response": {
"pass": false,
"routing": [
{
"unit_id": "review-routing",
"unit_type": "slide",
"treatment": "operating-model",
"confidence": "high",
"reason": "The claim depends on policy-based routing into distinct clinician queues."
}
],
"findings": [
{
"check_id": "operating-model-fit",
"unit_id": "review-routing",
"unit_type": "slide",
"evidence": "Four equal cards name review jobs but show no selection rule, mandatory path, protected probability sample, or deduplication.",
"fix": "Render the universal checks and policy router, then separate mandatory, representative, calibration, and frontier lanes."
}
]
}
}
16 changes: 16 additions & 0 deletions evals/fixtures/rubrics/operating-model-fit/routing-cases.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{"id":"section-hero-single-claim","unit_type":"section","narrative_job":"Open a report with one proposition.","visible_claim":"Clinical reasoning is the scarce asset.","expected_treatment":"none","expected_applicable":false,"rationale":"A dominant claim does not need a relational model."}
{"id":"section-quote","unit_type":"section","narrative_job":"Let one expert observation carry the argument.","visible_claim":"A physician quote with attribution.","expected_treatment":"none","expected_applicable":false,"rationale":"A quote is evidence, not a system."}
{"id":"section-single-kpi","unit_type":"section","narrative_job":"Establish one baseline number.","visible_claim":"Universal review consumes five minutes per task.","expected_treatment":"none","expected_applicable":false,"rationale":"One number and one qualifier need hierarchy, not a diagram."}
{"id":"section-faq","unit_type":"section","narrative_job":"Answer implementation questions in plain language.","visible_claim":"Four independent questions and answers.","expected_treatment":"none","expected_applicable":false,"rationale":"Independent answers remain a list."}
{"id":"section-pricing-compare","unit_type":"section","narrative_job":"Compare internal annotation cost with external licensing value.","visible_claim":"Two price bases and their ratio.","expected_treatment":"relational","expected_applicable":true,"rationale":"Aligned quantities make the comparison inspectable."}
{"id":"section-before-after","unit_type":"section","narrative_job":"Show how review allocation changes after launch.","visible_claim":"Universal stamping becomes sampled review.","expected_treatment":"relational","expected_applicable":true,"rationale":"A paired composition exposes the change without implying a process."}
{"id":"section-benchmark-matrix","unit_type":"section","narrative_job":"Compare benchmark coverage and saturation.","visible_claim":"Tasks mapped against modalities and measured abilities.","expected_treatment":"relational","expected_applicable":true,"rationale":"A matrix is the faithful form for exact mappings."}
{"id":"section-review-router","unit_type":"section","narrative_job":"Explain which work reaches clinicians and why.","visible_claim":"Policy routes cases into mandatory, representative, calibration, and frontier queues.","expected_treatment":"operating-model","expected_applicable":true,"rationale":"The selection rules and separate queues are the claim."}
{"id":"section-state-transition","unit_type":"section","narrative_job":"Explain how a case moves from evidence collection to adjudication.","visible_claim":"Case states have explicit gates and abstention paths.","expected_treatment":"operating-model","expected_applicable":true,"rationale":"State and gate semantics must remain visible."}
{"id":"section-causal-feedback","unit_type":"section","narrative_job":"Show how clinician labels improve future sampling.","visible_claim":"Errors update the judge, which changes the next frontier sample.","expected_treatment":"operating-model","expected_applicable":true,"rationale":"The feedback loop is causal, not a list of peers."}
{"id":"section-resource-to-gate","unit_type":"section","narrative_job":"Connect clinician hours to evidence and release decisions.","visible_claim":"Annotation creates eval evidence that controls model release.","expected_treatment":"operating-model","expected_applicable":true,"rationale":"The resource-to-decision chain is the strategic argument."}
{"id":"section-clinical-workspace","unit_type":"section","narrative_job":"Show how a physician investigates a multimodal case.","visible_claim":"A physician manipulates evidence, hypotheses, and next actions in one workspace.","expected_treatment":"simulated-surface","expected_applicable":true,"rationale":"The interaction model is more important than an abstract workflow."}
{"id":"slide-cover","unit_type":"slide","narrative_job":"Name the argument.","visible_claim":"Evals are strategic IP.","expected_treatment":"none","expected_applicable":false,"rationale":"The cover needs one focal statement."}
{"id":"slide-break-even","unit_type":"slide","narrative_job":"Make the review-cost threshold legible.","visible_claim":"Per-task cost times volume compared with benchmark investment.","expected_treatment":"relational","expected_applicable":true,"rationale":"An equation and paired totals are sufficient."}
{"id":"slide-review-router","unit_type":"slide","narrative_job":"Explain the new clinician allocation policy.","visible_claim":"Only selected cases reach distinct expert queues.","expected_treatment":"operating-model","expected_applicable":true,"rationale":"Policy routing is the claim."}
{"id":"slide-clinical-ide","unit_type":"slide","narrative_job":"Make the future training environment concrete.","visible_claim":"Physicians reason over multimodal evidence and probability-bearing hypotheses.","expected_treatment":"simulated-surface","expected_applicable":true,"rationale":"The product surface is the most faithful explanation."}
8 changes: 6 additions & 2 deletions evals/rubric-coverage.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
{
"note": "Tracks executable-fixture coverage for the 30 llm-pass/transcript catalog checks that evals/run.mjs cannot exercise (see plans/007-DESIGN-NOTE.md). Separate from evals/parity-allowlist.json, which is scoped to deterministic-stage (static-text/static-dom/browser) checks only.",
"total_llm_pass_and_transcript_checks": 30,
"note": "Tracks executable-fixture coverage for the 31 llm-pass/transcript catalog checks that evals/run.mjs cannot exercise (see plans/007-DESIGN-NOTE.md). Separate from evals/parity-allowlist.json, which is scoped to deterministic-stage (static-text/static-dom/browser) checks only. operating-model-fit also has a JSONL routing set covering slide and long-form section decisions.",
"behavioral_fixture_sets": {
"operating-model-fit": "evals/fixtures/rubrics/operating-model-fit/routing-cases.jsonl"
},
"total_llm_pass_and_transcript_checks": 31,
"covered_by_evals_run_rubrics": [
"text-visibly-clipped",
"fixed-ui-obscures-content",
"diagram-type-coherent",
"preset-both-mode-visual",
"deck-content-completeness",
"operating-model-fit",
"reel-caption-matches-transcript"
],
"remaining_uncovered": [
Expand Down
128 changes: 125 additions & 3 deletions evals/run-rubrics.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env node
// Regression suite for the 30 llm-pass/transcript catalog checks that
// Regression suite for the 31 llm-pass/transcript catalog checks that
// evals/run.mjs cannot exercise (it filters to static-text/static-dom/browser
// stages by design — see plans/007-DESIGN-NOTE.md for why).
//
Expand Down Expand Up @@ -28,18 +28,25 @@
import { readFileSync, readdirSync, existsSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { buildReport } from '../plugins/visual-explainer/scripts/verify/lib/report.mjs';

const EVAL_ROOT = dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = resolve(EVAL_ROOT, '..');
const RUBRICS_FIXTURES_ROOT = join(EVAL_ROOT, 'fixtures', 'rubrics');
const OPERATING_MODEL_ROUTING_CASES = join(
RUBRICS_FIXTURES_ROOT,
'operating-model-fit',
'routing-cases.jsonl',
);

const checksCatalog = JSON.parse(
readFileSync(resolve(REPO_ROOT, 'plugins/visual-explainer/scripts/verify/checks.json'), 'utf8'),
).checks;

const severityById = new Map(checksCatalog.map((check) => [check.id, check.severity]));

// The first implementation slice from plan 007 step 3: 6 checks, the
// The first implementation slice from plan 007 step 3, extended with the
// operating-model routing contract: 7 checks. The
// 13 error-severity uncovered checks are the priority pool this was drawn
// from. `mode: 'stub'` checks are asserted via deriveStatus() against a
// canned judge_response fixture; `mode: 'algorithm'` runs the real scorer.
Expand All @@ -49,6 +56,7 @@ const SLICE = [
{ id: 'diagram-type-coherent', mode: 'stub' },
{ id: 'preset-both-mode-visual', mode: 'stub' },
{ id: 'deck-content-completeness', mode: 'stub' },
{ id: 'operating-model-fit', mode: 'stub' },
{ id: 'reel-caption-matches-transcript', mode: 'algorithm' },
];

Expand Down Expand Up @@ -154,6 +162,118 @@ function runTranscriptCheck(id) {
return rows;
}

// --- Operating-model contract: routing set + section pass selection --------

function readJsonl(path) {
return readFileSync(path, 'utf8')
.split('\n')
.map((line) => line.trim())
.filter(Boolean)
.map((line, index) => {
try {
return JSON.parse(line);
} catch (error) {
throw new Error(`${path}:${index + 1}: ${error.message}`);
}
});
}

function runOperatingModelRoutingCases() {
const allowedTreatments = new Set([
'none',
'relational',
'operating-model',
'simulated-surface',
]);
const allowedUnitTypes = new Set(['slide', 'section']);
const cases = readJsonl(OPERATING_MODEL_ROUTING_CASES);
const seenIds = new Set();
const rows = [];

for (const fixture of cases) {
const errors = [];
if (!fixture.id || seenIds.has(fixture.id)) errors.push('id must be present and unique');
if (!allowedUnitTypes.has(fixture.unit_type)) errors.push('unit_type must be slide or section');
if (!allowedTreatments.has(fixture.expected_treatment)) errors.push('invalid expected_treatment');
if (typeof fixture.expected_applicable !== 'boolean') errors.push('expected_applicable must be boolean');
if (fixture.expected_applicable !== (fixture.expected_treatment !== 'none')) {
errors.push('expected_applicable must be false only for treatment=none');
}
if (!fixture.narrative_job || !fixture.visible_claim || !fixture.rationale) {
errors.push('narrative_job, visible_claim, and rationale are required');
}
seenIds.add(fixture.id);
rows.push({
id: 'operating-model-routing-case',
caseName: fixture.id || 'missing-id',
status: errors.length ? 'FAIL' : 'pass',
message: errors.length
? errors.join('; ')
: `${fixture.unit_type} -> ${fixture.expected_treatment}`,
});
}

const coverageAssertions = [
['covers-slide-units', cases.some((fixture) => fixture.unit_type === 'slide')],
['covers-section-units', cases.some((fixture) => fixture.unit_type === 'section')],
...Array.from(allowedTreatments, (treatment) => [
`covers-${treatment}`,
cases.some((fixture) => fixture.expected_treatment === treatment),
]),
];
for (const [caseName, pass] of coverageAssertions) {
rows.push({
id: 'operating-model-routing-coverage',
caseName,
status: pass ? 'pass' : 'FAIL',
message: pass ? 'covered' : 'missing',
});
}
return rows;
}

function runOperatingModelPassSelectionCases() {
const operatingModelCheck = {
id: 'operating-model-fit',
stage: 'llm-pass',
status: 'llm-required',
severity: 'warn',
};
const cases = [
{
name: 'sectioned-page',
ctx: { profile: 'page', preset: 'custom', presetHint: '', html: '<main><section>Case review</section></main>', filePath: 'sectioned.html' },
expected: true,
},
{
name: 'simple-page',
ctx: { profile: 'page', preset: 'custom', presetHint: '', html: '<main><div>One statement</div></main>', filePath: 'simple.html' },
expected: false,
},
{
name: 'vertical-deck',
ctx: { profile: 'slides', preset: 'custom', presetHint: '', html: '<main></main>', filePath: 'slides.html' },
expected: true,
},
{
name: 'presentation-stage',
ctx: { profile: 'page', preset: 'custom', presetHint: '', html: '<main data-ve-presentation></main>', filePath: 'stage.html' },
expected: true,
},
];

return cases.map(({ name, ctx, expected }) => {
const report = buildReport(ctx, [operatingModelCheck]);
const actual = report.llm_passes_required.includes('operating-model');
return {
id: 'operating-model-pass-selection',
caseName: name,
status: actual === expected ? 'pass' : 'FAIL',
message: `expected=${expected} actual=${actual}`,
};
});
}

// --- Driver ------------------------------------------------------------

const catalogIds = new Set(checksCatalog.map((check) => check.id));
Expand All @@ -168,6 +288,8 @@ for (const entry of SLICE) {
const rows = entry.mode === 'algorithm' ? runTranscriptCheck(entry.id) : runStubCheck(entry.id);
allRows.push(...rows);
}
allRows.push(...runOperatingModelRoutingCases());
allRows.push(...runOperatingModelPassSelectionCases());

console.log('check_id,case,status,detail');
for (const row of allRows) {
Expand All @@ -184,4 +306,4 @@ if (failures.length) {
}

const checksCovered = new Set(allRows.map((row) => row.id)).size;
console.log(`\nAll ${allRows.length} assertions passed across ${checksCovered} checks (fire + no-fire each).`);
console.log(`\nAll ${allRows.length} assertions passed across ${checksCovered} check families.`);
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@
"ve:eval-rubrics": "node evals/run-rubrics.mjs",
"check:manifests": "node scripts/check-manifests.mjs",
"ve:learn": "node scripts/ve-mdx/learn.mjs",
"test": "node --test visual-explainer-mdx/diagram-layout.test.mjs visual-explainer-mdx/presentation-core.test.mjs scripts/ve-mdx/design-systems.test.mjs scripts/ve-mdx/learn-extractors.test.mjs"
"test": "node --test visual-explainer-mdx/diagram-layout.test.mjs visual-explainer-mdx/presentation-core.test.mjs scripts/ve-mdx/design-systems.test.mjs scripts/ve-mdx/export-react-singleton.test.mjs scripts/ve-mdx/learn-extractors.test.mjs"
},
"dependencies": {
"@mdx-js/rollup": "^3.1.1",
"@tailwindcss/vite": "^4.3.0",
"@vitejs/plugin-react": "^6.0.1",
"react": "^19.2.6",
"react-dom": "^19.2.6",
"react": "19.2.7",
"react-dom": "19.2.7",
"tailwindcss": "^4.3.0",
"typescript": "^6.0.3",
"vite": "^8.0.12"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
name: ve-verifier-operating-model
description: Route each slide or coherent page section to the minimum explanatory treatment and judge operating-model fidelity only where applicable. Returns only verdict JSON.
tools: Read
---

# ve-verifier-operating-model

Run one verification pass. Do not fix files.

## Read

1. `plugins/visual-explainer/scripts/verify/rubrics/pass-operating-model.md`
2. One screenshot per review unit: slide, presented stage, or coherent page section.
3. The review map supplied by the orchestrator: unit id, unit type, visible title, and one-sentence narrative job.
4. Only the brief excerpts needed to resolve a unit's intended decision.

Route every unit before judging it. Do not penalize `none` units for lacking a
diagram. Do not infer intent from implementation source.

## Output

Return only one valid JSON object matching the rubric schema:

```json
{"pass":true,"routing":[],"findings":[]}
```

Do not include prose, markdown, code fences, summaries, or recommendations
outside `routing` and `findings`.
Loading
Loading