UNDER THE HOOD

FOR THE LARP — Every prediction has a provenance.

Model outputs on this page are recorded evidence, each stamped with its date and build SHA. Every number in sections 3 to 6 is computed live in your browser by the same code production runs. This page makes no model calls and holds no keys.

1 The runtime pipeline

Two vision models read pixels; one router reads text; a human confirms; deterministic code does all the math. Select a stage.

on failureGroq visionqwen/qwen3.8-27bGemini vision fallbackgemini-3.5-flash-liteNormalize + validatezod, deterministicJev routerjev-1.13-free(BeatAPI)Human confirmationthe user, in /labMNA solverlocal TS, no modelDiagnosis + Probesolver re-runs, nomodelGrounded tutorgemini-3.5-flash-lite

MODEL CALL (server-only)

Jev router

jev-1.13-free (BeatAPI)

Inputs
Structured TEXT state only (component list, measure node, warnings, unresolved connections, validation errors). Never pixels.
Outputs
One choice: review_extraction / verify_topology / ask_user, with probabilities. verify_topology triggers one Groq verifier read (src/lib/ai/secondary.ts) that passes the same normalizer.
Code
src/lib/ai/jev.tssrc/lib/ai/secondary.ts
Failure behavior
No key, a paid model id, free-tier pacing (1 call/min, waits at most 8 s), 429 (Retry-After honoured) or a 15 s timeout all default to ask_user with an honest 'skipped'/'error' trace row. Paid jev-1.13 is refused in code.

2 Recorded traces

Real trace arrays returned by production, copied from the repo's evidence docs. Static data: replaying them here costs no quota.

RECORDED on 2026-10-11 12:51:28 PDT, build d1096b7

Input: public/samples/clear-divider.png

stepprovider / modelstatusmstokens in / outnote
extractgroq / qwen/qwen3.8-27bok8391208 / 211
routebeatapi / jev-1.13-freeok711not recordedreview_extraction, p=1.00

Outcome: Exact graph (V1 5 V, R1 10k, R2 10k); user reviews and confirms.

Also observed ~12:30 PM PDT on build a9f6360: groq ok 795 ms, Jev review_extraction p=1.00 (docs/RELEASE_REPORT.md; tokens not recorded in that row).

Source: docs/demo/README.md (recorded backup run); README.md

3 Topology & validation

Models never hand the solver a picture. They hand it this typed graph, which validateGraph (zod schema + graph walk from GND) must accept before anything is solved. The checks below run in your browser.

// src/lib/circuit/types.ts (canonical contract, docs/API_CONTRACT.md v1)
export type CircuitComponent = {
  id: string;
  kind: 'resistor' | 'dc_voltage';
  value: number; // SI units: ohm or volt
  positiveNode: string;
  negativeNode: string;
  sourceBoundingBox?: [number, number, number, number];
};
export type CircuitGraph = {
  schemaVersion: 1;
  components: CircuitComponent[];
  groundNode: 'GND';
  measureNode: string;
};
V15 VR110 kΩR210 kΩVINVOUTGND
Electrical connections

validateGraph: ok (3 components, measure VOUT)

Graph JSON
{
 "schemaVersion": 1,
 "components": [
  {
   "id": "V1",
   "kind": "dc_voltage",
   "value": 5,
   "positiveNode": "VIN",
   "negativeNode": "GND"
  },
  {
   "id": "R1",
   "kind": "resistor",
   "value": 10000,
   "positiveNode": "VIN",
   "negativeNode": "VOUT"
  },
  {
   "id": "R2",
   "kind": "resistor",
   "value": 10000,
   "positiveNode": "VOUT",
   "negativeNode": "GND"
  }
 ],
 "groundNode": "GND",
 "measureNode": "VOUT"
}

4 MNA solver: the only math authority

Modified Nodal Analysis stamps each resistor as a conductance into G and each ideal source as a row/column pair (B, C), then solves [G B; C D]·[v; j] = [i; e] by Gaussian elimination with partial pivoting. solveDC keeps its matrix private, so this page re-derives it with the same stamps (src/app/for-the-larp/math.ts) and checks the result against solveDC live; a unit test pins it. Fixture: Divider 5 V, 10k/10k.

v(VIN)v(VOUT)i(V1)bx (solved)
KCL @ VIN105 V
KCL @ VOUT002.5 V
V1 equation1005-0.25 mA

G[VIN, VIN] = 1/R1 S. Select a conductance cell to inspect its resistor contributions.

G conductances (S) B/C source incidence D zero for ideal sources. Source current follows MNA sign: current into the + terminal, so a source delivering power reads negative.

solveDC() in this browser returns VIN = 5 V, VOUT = 2.5 V: bit-for-bit identical to the displayed x.

5 Predictions & evidence

Drag the meter reading. diagnose() re-solves the circuit with each part open, shorted, off-value or each supply off-rail, and ranks single-fault hypotheses that reproduce your reading. No model, no network: everything below recomputes in your browser.

PREDICTION (solver)2.5 Vat VOUT
EVIDENCE (your meter)0.45 VΔ -2.05 V
  1. R2 may be 1 kΩ instead of 10 kΩ

    Expected 2.5 V at VOUT but measured 0.45 V. Hypothesis: a 1 kΩ R2 would give 0.455 V (exact fit 989 Ω), instead of the 10 kΩ in the diagram. A wrong resistor value or misread color band is one possible explanation. This is a hypothesis, not a confirmed fault.

    Next: Disconnect power first, then measure R2's resistance with a multimeter and compare to 10 kΩ.

  2. R1 may be 100 kΩ instead of 10 kΩ

    Expected 2.5 V at VOUT but measured 0.45 V. Hypothesis: a 100 kΩ R1 would give 0.455 V (exact fit 101 kΩ), instead of the 10 kΩ in the diagram. A wrong resistor value or misread color band is one possible explanation. This is a hypothesis, not a confirmed fault.

    Next: Disconnect power first, then measure R1's resistance with a multimeter and compare to 10 kΩ.

  3. Supply V1 may be 0.9 V instead of 5 V

    Expected 2.5 V at VOUT but measured 0.45 V. Hypothesis: if V1 were actually delivering about 0.9 V instead of 5 V, the reading would match (low battery, wrong supply or regulator setting). This is a hypothesis, not a confirmed fault.

    Next: With the circuit powered, measure the voltage directly across V1's terminals (low-voltage DC only) and compare to 5 V.

6 Probe Guide: where to measure next

probeStep() builds 1 nominal + 13 single-fault hypotheses (each resistor open, shorted, ×10, ×0.1; supply dead), re-solves each with MNA, and weights them by a Gaussian meter model (σ = 2% + 10 mV). For each unmeasured node it groups hypotheses whose predicted readings a meter can't tell apart and computes expected information gain IG = H(posterior) − Σ P(outcome)·H(posterior | outcome) in bits. Highest gain wins. Computed live below.

V15 V+R110 kΩR210 kΩR310 kΩVINGNDAB
Electrical connections

Ladder: V1 = 5 V, R1, R2, R3 = 10 kΩ in series. Expected B = 1.667 V. Readings: B = 0 V.

probe nodeexpected gain
VIN 0.81 bits
A 1.50 bits← probeStep picks

Measure A next (~1.50 bits expected).

  • ≈ 0 V → 50%: V1:dead, R1:open
  • ≈ 2.5 V → 25%: R3:short
  • ≈ 5 V → 25%: R2:open

Posterior (top 5)

  • Supply V1 off / dead / disconnected25%
  • R3 shorted (bridge or stray wire)25%
  • R1 open / not connected25%
  • R2 open / not connected25%
  • No single modeled fault fits these readings1%

7 Usage, latency, limits & economics

Measured anecdotes, not distributions. Unknown is written as unknown, never as $0. Sources: docs/UNIT_ECONOMICS.md, docs/MODEL_ACCESS.md, docs/VISION_FALLBACK.md, docs/demo/README.md.

Measured (2026-10-11, production)

stagemodellatencytokens in / outsource
Extract (current primary)qwen/qwen3.8-27b (Groq)839 ms1208 / 211clear divider, 12:51 PDT, d1096b7 (docs/demo/README.md)
Extract, 10 synthetic fixturesqwen/qwen3.8-27b (Groq)735 ms median1208 / 23310/10 exact, 0 API errors; not a benchmark (docs/VISION_FALLBACK.md)
Extract (fallback)gemini-3.5-flash-lite1140 ms1310 / 22912:52 PDT, d1096b7 (docs/demo/README.md)
Extract (Gemini-primary era)gemini-3.5-flash3790 ms1310 / 106docs/UNIT_ECONOMICS.md
Routejev-1.13-free (BeatAPI)440 ms475 / 49same Gemini-era run (docs/UNIT_ECONOMICS.md)
Solvelocal MNA~1 msn/adocs/UNIT_ECONOMICS.md

Free-plan ceilings and listed prices (accessed 2026-10-11)

providerfree-plan limitpaid price
Jev jev-1.13-free (BeatAPI)1 successful call/min before any top-up (binding: 1 analysis/min)jev-1.13: $0.042 / 1M input, output free; refused in code
Groq qwen/qwen3.8-27b30 RPM, 1K RPD, 8K TPM, 200K TPD; ~2.5k tokens per image call ⇒ ~3 extractions/minnot listed (groq.com/pricing)
Gemini (fallback + tutor)not listed (AI Studio only); free quota observed exhausted (429) on 2026-10-11gemini-3.5-flash: not listed
App guard (src/proxy.ts)per IP: extract 6/min + 40/h, solve 60/min, explain 10/minn/a

Usage charges in this deployment: $0 by construction (free plans), which is not a production marginal-cost claim. Hypothetical paid cost per analysis (scripts/cost-model.mjs): Jev $0.0000200; Groq and Gemini unknown until their prices are listed, so the total is incomplete. No routing-savings claim: there is no same-case baseline yet.

8 Supported today vs planned

Works today

  • DC resistive networks: resistors + ideal DC voltage sources
  • Clean schematic images (synthetic renders; real-photo accuracy unmeasured)
  • Single-fault hypotheses: open, short, off-value resistor, off-rail supply
  • Probe Guide (information gain) and solver-grounded tutor
  • Routes review_extraction and ask_user observed on the Groq-primary pipeline

Planned / research (not shipped)

  • Topology confidence engine: research, PR #39 (open, not merged)
  • verify_topology on the Groq-primary stack: implemented, not yet observed live
  • Breadboard and netlist adapters: planned
  • Capacitors, inductors, AC and transient analysis: research
  • PCB/EDA imports: exploration
  • Multiple simultaneous faults: not modeled (a fit warning says so)