TYPE MODEL BENCH
EVALUATION · TYPESAFE JEV · MIRO

Jev tells flawed types from clean ones, but cannot name redundant or overloaded states

Given the domain's required states, it sorts 84% of TypeScript types correctly into flawed or compliant and names illegal and missing states reliably. Redundant and overloaded encodings it mostly waves through as compliant or mislabels as missing.

jev-1.13.0 · 576 TYPES · 24 DOMAINS · 1 CHOICE + 4 NOUL PER REQUEST · 2026-09-17
5-WAY · ALL
59.2%
SPEC 68 · BLIND 51
FLAW FOUND · SPEC
83.7%
RECALL 89 · PREC 87
ILLEGAL · AUC SPEC
0.98
RELIABLE
SUBTLE FLAWS · SPEC
39.7%
OBVIOUS 82
SAMPLES
576
24 DOMAINS · 4 VARIANTS EACH
COST
0.034USD
813K TOK · P50 286 MS
WHAT WAS TESTEDCORPUS · QUESTIONS

Corpus. 24 everyday domains (an inbox loading, a traffic light, an order, a WebSocket, a cinema seat…). Each has a written list of the abstract states it must distinguish, two hand-written compliant encodings, and one flawed encoding per MIRO letter. Every flawed snippet carries exactly one flaw, graded obvious or subtle. That gives 144 base snippets.

Axes. Each snippet is sent four times. spec puts the required-states list in the state; blind gives only a one-line domain description. plain sends the type alone; noise prepends an unrelated well-formed type as a distractor. Same snippet, four cells: comparisons are paired.

Questions. One request per sample carrying a five-option choice (compliant plus the four letters, each with what, not_for and examples) and four independent noul detectors, one per letter. Ground truth is the authored label; a verdict is correct only if it names the exact class.

ClassDefinition used in the promptN
compliantEvery abstract state has exactly one concrete value and vice versa.192
missingAn abstract state, or data a state must carry, has no representation.96
illegalThe type admits a value or field combination with no meaning.96
redundantTwo distinct concrete values encode the same abstract state.96
overloadedOne concrete value stands for two abstract states the domain must tell apart.96
ONE REQUEST, VERBATIMorder.overloaded.spec.plain · 332 MS · 1424 TOK IN

What Jev sees. The blog post is not in the request. MIRO reaches the model only through the question text below: one instruction line, then a what, a not_for and two examples per letter, written by hand from the post. The state carries the domain, the required-states list (spec condition only), the type and one note about branded aliases. Nothing else. All 576 requests have this exact shape; only state changes.

This sample. Authored label overloaded: 'open' stands for both 'awaiting payment' and 'paid, awaiting shipment'. Jev answers missing at 0.96 — the single most common confusion in the run.

REQUEST · POST api.typesafe.ai/v1/systemoneAUTHORIZATION: BEARER …
{
  "state": {
    "domain": "Lifecycle of a customer order in a web shop",
    "required_states": [
      "Placed, awaiting payment",
      "Paid, awaiting shipment",
      "Shipped, with a carrier tracking number",
      "Delivered",
      "Cancelled, with the reason recorded"
    ],
    "type_definition": "type Order =\n  | { status: 'open' }\n  | { status: 'shipped'; tracking: TrackingNumber }\n  | { status: 'delivered' }\n  | { status: 'cancelled'; reason: string };",
    "notes": "Branded aliases (UserId, Celsius, Percent, Milliseconds, Url, Cents, ...) are defined elsewhere."
  },
  "model": "jev-latest",
  "questions": {
    "verdict": {
      "type": "choice",
      "instructions": "Judge `type_definition` against the MIRO checklist for state modelling. The abstract states are the situations the domain in `domain` must distinguish (listed in `required_states` when present). The concrete states are the values the TypeScript type admits. A compliant type maps abstract states one-to-one onto concrete values. Pick the single most serious problem, or `compliant` if the mapping is one-to-one. `notes` explains helper aliases; do not treat them as problems.",
      "criteria": {
        "compliant": {
          "what": "Every abstract state has exactly one concrete value and every concrete value means exactly one abstract state.",
          "not_for": "Types that merely look tidy; check each required situation is expressible and no field combination is meaningless."
        },
        "missing": {
          "what": "An abstract state the domain needs cannot be expressed at all by the type, or a piece of data a state must carry has nowhere to live.",
          "not_for": "States that are expressible but share a value with another state (that is overloaded).",
          "examples": [
            "No branch for 'cancelled' although orders can be cancelled",
            "A 'read' state that must record a time but has no time field"
          ]
        },
        "illegal": {
          "what": "The type admits a combination of field values that has no meaning in the domain, typically independent optional fields or booleans that should be mutually exclusive.",
          "not_for": "Union types whose branches each carry only the data that branch needs.",
          "examples": [
            "{ loading: true, error: 'x', data: [...] } all at once",
            "Three independent boolean lamps that can all be true"
          ]
        },
        "redundant": {
          "what": "Two or more distinct concrete values encode the same abstract state: duplicate variant names, two fields that restate one fact, or a field whose value is ignored in some branch.",
          "not_for": "Distinct variants that only look similar but mean different situations.",
          "examples": [
            "Both 'cancelled' and 'canceled' variants",
            "position in ms and in seconds side by side",
            "A target temperature carried in the 'off' branch"
          ]
        },
        "overloaded": {
          "what": "One concrete value stands for two or more abstract states that the domain must tell apart; the reader cannot recover which one is meant.",
          "not_for": "A value that genuinely means one thing even if the name is vague.",
          "examples": [
            "null meaning both 'not asked yet' and 'explicitly off'",
            "A 'stopped' variant covering both 'paused' and 'finished'"
          ]
        }
      }
    },
    "has_missing": {
      "type": "noul",
      "instructions": "Does `type_definition` exhibit the MIRO 'missing' problem for the domain in `domain`? An abstract state or required piece of data has no representation.",
      "criteria": {
        "true": "Yes: at least one clear instance of the 'missing' problem is present.",
        "false": "No: the type is free of the 'missing' problem, whatever other problems it may have."
      }
    },
    "has_illegal": {
      "type": "noul",
      "instructions": "Does `type_definition` exhibit the MIRO 'illegal' problem for the domain in `domain`? The type admits a value or field combination with no meaning in the domain.",
      "criteria": {
        "true": "Yes: at least one clear instance of the 'illegal' problem is present.",
        "false": "No: the type is free of the 'illegal' problem, whatever other problems it may have."
      }
    },
    "has_redundant": {
      "type": "noul",
      "instructions": "Does `type_definition` exhibit the MIRO 'redundant' problem for the domain in `domain`? Two distinct concrete values encode the same abstract state.",
      "criteria": {
        "true": "Yes: at least one clear instance of the 'redundant' problem is present.",
        "false": "No: the type is free of the 'redundant' problem, whatever other problems it may have."
      }
    },
    "has_overloaded": {
      "type": "noul",
      "instructions": "Does `type_definition` exhibit the MIRO 'overloaded' problem for the domain in `domain`? One concrete value stands for two different abstract states.",
      "criteria": {
        "true": "Yes: at least one clear instance of the 'overloaded' problem is present.",
        "false": "No: the type is free of the 'overloaded' problem, whatever other problems it may have."
      }
    }
  }
}
RESPONSE · HTTP 200jev-1.13.0
{
  "model": "jev-1.13.0",
  "answers": {
    "verdict": {
      "type": "choice",
      "choice": "missing",
      "confidence": 0.95,
      "probabilities": {
        "overloaded": 0.04,
        "compliant": 0.0,
        "illegal": 0.0,
        "redundant": 0.0,
        "missing": 0.96
      }
    },
    "has_missing": {
      "type": "noul",
      "noul": 0.95
    },
    "has_illegal": {
      "type": "noul",
      "noul": 0.57
    },
    "has_redundant": {
      "type": "noul",
      "noul": 0.19
    },
    "has_overloaded": {
      "type": "noul",
      "noul": 0.51
    }
  },
  "usage": {
    "input_tokens": 1424,
    "output_tokens": 135
  }
}
WHERE VERDICTS LANDROWS = TRUTH · COLS = JEV · SHADE = SHARE OF ROW
SPEC · REQUIRED STATES GIVEN
BLIND · DOMAIN LINE ONLY

With the spec, missing is caught 98% of the time; blind, 0%. A reviewer cannot know what is missing without the list of what must exist, and neither can Jev.

Overloaded types are read as missing 30 of 48 times under spec: a value that means two things does lose a distinction, so the confusion is between two true descriptions of one type. Redundant types pass as compliant 18 of 48 times: duplicates that add no illegal value look harmless.

PER CLASS · SPECN = 288
TruthNPrec %Recall %F1State
compliant9676740.75warn
missing4853980.69warn
illegal48100880.93ok
redundant48100380.55warn
overloaded4837350.36crit
PER CLASS · BLINDN = 288
TruthNPrec %Recall %F1State
compliant9642990.59warn
missing48000.00crit
illegal4892770.84ok
redundant4875250.38crit
overloaded4810040.08crit
CONDITION × PRESENTATION144 PER CELL
CondPres5-way accuracyFlaw recall %Compliant kept %
specplain
70%
8979
specnoise
65%
8969
blindplain
51%
31100
blindnoise
50%
3298

The spec is worth about 17 points; the distractor type costs about 3. Naming the states matters far more than keeping the input clean.

DIFFICULTYAUTHORED TIER
TierTypical flawNSpecAll
compliantNo flaw; both encodings per domain192
74%
86%
obviousWhole variant absent, duplicate variant name, independent booleans228
82%
61%
subtleIgnored field in one branch, two units for one fact, null with two meanings156
40%
24%

Obvious flaws (a variant that is simply absent, three independent booleans) are found. Subtle ones (a field that is ignored in one branch, a null that means two things) mostly are not.

NOUL DETECTORS · SPECROC PER LETTER · HOVER FOR THRESHOLD
DetectorAUC specAUC allBest cutPrec %Recall %State
has_missing0.940.760.936943ok
has_illegal0.980.950.716982ok
has_redundant0.720.710.463257warn
has_overloaded0.810.630.634532ok

A noul is a probability of yes; the ROC shows every cut at once. The best cut and its precision and recall are computed on all 576 samples, so treat them as an upper bound: they were picked on the same data they are scored on.

Positive = the sample's authored flaw is that letter. Negatives include compliant types and the other three flaws.

CALIBRATION · CHOICE CONFIDENCEECE 0.154

Confidence is how concentrated the probability mass is, not a promise of accuracy. Above 0.9 it is worth something; between 0.3 and 0.9 accuracy is flat.

CALIBRATION TABLEALL 576
BinNMean conf %Accuracy %
0.1–0.241725
0.2–0.3372538
0.3–0.4563554
0.4–0.5704561
0.5–0.6625453
0.6–0.7846554
0.7–0.8817560
0.8–0.9718555
0.9–1.01119578
PER DOMAIN24 PER DOMAIN · 12 PER CONDITION
DomainDescriptionSpecBlindMissed classes
traffic_lightA road traffic light controller
100%
83%
missing ×2
media_playerPlayback state of an audio player
83%
67%
overloaded ×4, missing ×2
calendar_eventScheduling of a calendar event
75%
67%
overloaded ×3, compliant ×2, missing ×2
ovenA kitchen oven's control state
83%
50%
redundant ×4, missing ×2, overloaded ×2
uploadUploading a single file from a form
83%
50%
overloaded ×4, redundant ×2, missing ×2
invoiceAn invoice sent to a client
67%
67%
compliant ×3, overloaded ×3, missing ×2
form_fieldValidation state of a single text field in a form
83%
50%
overloaded ×4, missing ×2, redundant ×2
discountDiscount applied to a shopping cart
75%
50%
redundant ×4, overloaded ×3, missing ×2
feature_flagRollout state of a feature flag
83%
42%
redundant ×4, missing ×2, overloaded ×2, illegal ×1
audio_fxExtra audio effects setting in a music player
67%
50%
illegal ×4, overloaded ×2, compliant ×2, missing ×2
auth_sessionBrowser session for a web app
67%
50%
redundant ×4, missing ×2, overloaded ×2, illegal ×1, compliant ×1
orderLifecycle of a customer order in a web shop
67%
50%
overloaded ×4, compliant ×2, missing ×2, illegal ×2
shipping_addressShipping address selection at checkout
67%
50%
overloaded ×4, redundant ×4, missing ×2
elevatorAn elevator car
67%
50%
redundant ×4, overloaded ×4, missing ×2
message_listLoading a user's message inbox from the server
58%
50%
overloaded ×4, redundant ×4, missing ×3
door_lockA smart door lock
67%
42%
redundant ×4, compliant ×3, missing ×2, overloaded ×2
background_jobA background job in a task queue
75%
33%
overloaded ×4, illegal ×3, missing ×2, redundant ×2
thermostatA home thermostat schedule entry
67%
33%
redundant ×4, illegal ×4, missing ×2, overloaded ×2
chat_messageDelivery state of an outgoing chat message
50%
50%
overloaded ×4, redundant ×4, missing ×2, compliant ×2
search_boxA search box with server-side results
50%
50%
overloaded ×4, redundant ×4, compliant ×2, missing ×2
ws_connectionA WebSocket connection managed by a client library
50%
50%
redundant ×4, overloaded ×4, compliant ×2, missing ×2
seat_bookingA seat in a cinema booking system
50%
50%
overloaded ×4, redundant ×4, missing ×2, compliant ×2
pr_reviewReview state of a pull request
42%
50%
redundant ×4, overloaded ×4, compliant ×3, missing ×2
subscriptionA SaaS subscription's billing state
50%
33%
redundant ×4, overloaded ×4, missing ×2, illegal ×2, compliant ×2
EVERY SAMPLECLICK A ROW FOR THE TYPE, THE AUTHORED REASON AND THE FULL DISTRIBUTION
IDTruthVerdictConfTierCondPres
CAVEATSREAD BEFORE QUOTING A NUMBER
  • The corpus and its labels were written by Claude in one sitting, not sampled from real code. The flaw taxonomy follows the MIRO article; the tier grading is an author's judgment.
  • Each flawed snippet has one intended flaw. Some arguably carry a second one; the choice question asks for the most serious, and a defensible second reading is scored as wrong.
  • Classes are not balanced: 192 compliant, 96 per flaw. Binary flaw-detection numbers are the ones to compare across conditions.
  • Under blind, "missing" has no fair answer; those 96 samples cap the blind accuracy.
  • One prompt design, one run, no retries on disagreement. Prompt wording moves these numbers; nothing here was tuned against the results.
  • Single-request latency and cost at concurrency 8; rate limits were not approached.