Building Contour, a physics-grounded fit engine for fashion: the same body is a 29 in raw selvedge and a 28 in stretch denim, beating the size chart by 40 points.
Fashion TechEcommerceRetail Technology

The same body is a 29 in one jean and a 28 in another. I built the fit engine that explains why a size chart can't tell them apart.

Ashutosh SinghalAshutosh SinghalJuly 10, 202612 min read

I built this demo to settle an argument I kept having with myself, and it took one dropdown to end it. I had a synthetic shopper I called Riley, a fixed set of body measurements, and a catalog of eight synthetic jeans. I put Riley in front of the Ironside, a 14oz raw selvedge straight jean, rigid, zero stretch, and the engine came back with Size 29, 95% confidence, comfortable at every zone. Then I changed nothing about Riley, swapped the garment to the Driftwood, a stretch slim jean that looks almost identical in a product photo, and the correct size dropped to 28.

Same body. Same measurements. Two different correct sizes. And a waist-only size chart, the thing almost every apparel site actually uses today, would have printed the exact same number for both jeans and been wrong on one of them.

Contour recommending Size 29 at 95% confidence for Riley on the Ironside raw selvedge jean, with a note that a waist-only chart would say Size 28 and be wrong, and per-zone strain bars all reading comfortable
Riley on the rigid Ironside raw selvedge: the engine returns Size 29 at 95% confidence, every zone comfortable, and flags that a waist-only chart would have said 28. On this zero-stretch denim, 28 would blow past the thigh's stretch limit.

The product I ended up with is called Contour, and you can run this exact comparison yourself at https://veriprajna.com/demos/ai-fit-prediction-fashion. But the thing I want to talk about is not the recommendation. It is the reason the recommendation changed when nothing about the body did, because that reason is the whole argument for building this the way I built it.

Fashion has been trying to fix returns with better pictures

I started this project believing, like most people in this space, that the returns problem was an imaging problem. Apparel returns are dominated by fit, and the fit-related share runs somewhere between 53 and 67 percent, with about 63 percent of shoppers admitting they bracket, ordering two sizes and sending one back (Veriprajna WP34 research, 2026). The reverse logistics eat the margin. The industry's answer has been to make the picture better: richer size charts, then 3D avatars, then generative virtual try-on that renders the garment onto a photo of your body.

I spent a while convinced a good enough try-on would close the gap, and then I sat with what a try-on actually shows you. It shows you the jeans on a body. It does not show you whether those jeans will fit that body. A generative image can drape a fabric convincingly and have no idea that when Riley sits down, the thigh circumference exceeds what that specific denim can stretch to. The picture looks right. The seam is under load the render never computed.

A virtual try-on can show you the jeans on your body and still have no idea whether they will fit.

That was the sentence that reframed the project for me. A size chart is four one-dimensional numbers pretending to describe a three-dimensional body, and a try-on image is a pretty two-dimensional render pretending to be fit data. They share the same blindness. Neither of them can feel the fabric. Whether a garment fits is not a visual question. It is a mechanical one: the circumferential strain at each body zone measured against that fabric's elastic limit. And that is why Riley is a 29 in raw selvedge and a 28 in stretch denim even when the size chart is identical.

Contour recommending Size 28 for the same shopper Riley on the Driftwood stretch slim jean, noting that here the waist-only chart also lands on 28 because the stretch forgives the other zones
The same Riley, now on the Driftwood stretch slim. The correct size drops to 28 at 90% confidence, because the stretch denim forgives the thigh and hip that the rigid selvedge would not. The garment changed, the body did not, and the answer moved.

Why did I stop trusting the model to pick the size?

I let a language model choose the size once, early on, and watching it be confidently wrong is the reason the architecture looks the way it does now. My first instinct was the obvious one: feed the model the body, feed it the garment, ask it for a size. It answered instantly and fluently and, on the rigid fabrics, it was often wrong in the most dangerous way, wrong with high confidence. It had learned the shape of a plausible sizing answer without doing the one calculation that decides the truth.

So I pulled the decision out of the model entirely. In Contour, the size is computed in plain, unit-tested Python. For each candidate size the engine calculates zone_strain = (body_circumference − garment_finished_circumference) / garment_finished_circumference at every zone, compares it to the fabric's elastic comfort limit, and picks the size with the lowest total per-zone regret. Eight unit tests pin that physics in place. There is no model anywhere in the path that decides your size. The language model still has a job, reading messy vendor copy into a structured fabric spec, and phrasing the result into "snug at hip, relaxed at thigh." It advises. It never decides.

Agents advise, code decides. The moment the model gets a vote on the number, you have lost the thing that made the number trustworthy.

This is also the part of the thesis that does not age out, and it is the answer I give the engineers who ask why I did not just wait for a better model. A perfect language model still would not remove the need for the fabric mechanics, the body geometry, the per-zone strain calc, and the abstain policy. Even a flawless advisor has to be checked against a computed quantity to be safe at checkout. The model is one swappable advisor inside the machine. The machine is the product.

The size it refuses to guess

I almost shipped a version that never says "I don't know," and I am glad a stubborn test case talked me out of it. The shopper was Jordan, on that same rigid Ironside selvedge. I ran the fit check expecting a clean number and instead the engine surfaced a genuine conflict: at the smaller sizes the thigh blows past the fabric's stretch limit, and at the larger sizes the waist runs loose. On a zero-stretch denim there is simply no size that clears every zone. The waist-only chart, meanwhile, prints a confident 28 and moves on.

Contour abstaining on Jordan on the Ironside jean, showing a genuine fit conflict, recommending Size 31 as the least-bad at 58% confidence with the waist and hip loose and the advice to bracket or speak to a stylist
Jordan on the rigid Ironside: waist and hip run loose (-8% and -6%), the thigh runs snug, and no size is clean everywhere. The engine names the least-bad size (31) at 58% confidence and abstains, saying "bracket or speak to a stylist," instead of bluffing a number like the chart's confident 28.

The tempting move, the one that makes your headline accuracy look better, is to always print the least-bad size and call it a recommendation. I wrote that version. Then I made the engine abstain instead: it names the least-bad size, drops the confidence to 0.58, and says out loud, "bracket, or speak to a stylist." Across the full evaluation it does this on 33 of 105 body-by-garment pairs rather than guess. An honest "no single size is clean here" is worth more to a shopper than a confident wrong 28, because the confident wrong 28 is exactly how you get a return. Refusing to answer turned out to be a feature I had to fight my own benchmark instincts to keep.

The vendor copy that can't be true

I have a garment in the catalog that exists only to be rejected, and it came out of a real irritation with how product copy is written. The Maverick is described by its own vendor as "100% cotton raw selvedge denim with 4-way stretch." That claim is physically incoherent. A rigid woven raw selvedge cannot also be four-way stretch. But a naive extractor reads "4-way stretch," happily assumes the fabric forgives everything, and hands you a dangerously wrong size with a smile.

So between the extraction and the decision I put an adversarial critic. It checks the extracted fabric spec against physical constraints, and when the copy contradicts itself, it blocks the inference and routes to human review. No size recommendation is issued. The deterministic rules have the final say, not the model that read the copy.

Contour blocking the Maverick jean whose vendor copy claims raw selvedge and 4-way stretch, with a critic message that the fabric inference was rejected as mechanically incompatible and routed to human review with no size issued
The Maverick's copy claims "raw selvedge" and "4-way stretch" at once. The critic rejects the inference as mechanically incompatible, a rigid woven cannot be four-way stretch, and routes it to human review with no recommendation issued, rather than launder a contradiction into a confident size.

I keep this example on screen because it is the honest version of "AI safety" for this problem. The failure mode is not the model being creative. It is the model being obediently wrong about a garment whose own description lies. A system that always answers will answer here too, and it will be exactly as confident about the Maverick as it was about a jean whose copy was true. The whole point is to have a layer that can say "these two facts cannot both hold," and stop.

What the numbers actually say, and what they don't

I care about the benchmark, and I care even more about stating its scope honestly, because the honest number is the durable one. On a labeled 105-pair synthetic golden set, 15 bodies against 7 scored garments, Contour's engine scores 100 percent against the waist-only size chart's 60 percent. It eliminates bracketing on 67.6 percent of pairs, meaning the shopper gets one high-confidence size and does not need to order two, and it catches 39 fit conflicts, cases where the chart's waist-match picks a size the strain model proves fails at another zone.

Contour's benchmark panel showing 100 percent engine accuracy versus 60 percent for the waist-only baseline, a plus 40 point lift, 105 fits scored, 39 conflicts caught, and 67.6 percent single-size, with a per-shopper table for the raw selvedge jean
The benchmark: engine 100% vs the waist-only chart's 60% on the 105-pair set, a +40-point lift, with 39 conflicts caught and bracketing eliminated on 67.6% of pairs. On the rigid selvedge (top table) the chart drops to 33%, exactly where fit is hardest.

Here is the part I refuse to round off. That golden set is synthetic, and its labels use the same measurable fabric-stretch figures the engine uses, so it is not a fully independent oracle. The 100 percent is a property of this constructed set, not a promise of perfect fit prediction in the open world, and I will not let anyone quote it as one. The number I actually stand behind is the +40-point lift over the real incumbent method, the waist-only chart that most stores run today, measured on the same labels. That advantage is largest exactly where it should be: on the rigid selvedge and tailoring, where the chart falls to 33 percent, because a rigid fabric punishes a wrong size and a stretchy knit forgives it. Where the physics bites hardest is where a picture helps least, and where this engine earns its keep.

The honest headline is not "100% accurate." It is "40 points better than the chart your store already trusts, and most of that gap is in denim."

Every one of those recommendations also writes a replayable JSON receipt: the extracted fabric spec with the exact source phrases that drove each parameter, the full per-size strain matrix, and the final decision. So the answer is not just a number. It is a number you can open up and cross-examine, and the same payload is served at an /api/fit endpoint an AI shopping agent can call directly. As commerce moves toward agents that transact for us, the sizing signal they consume has to be machine-readable, confidence-scored, and auditable. A report, not a picture.

The question I keep coming back to

I went into this thinking I was building a better guesser, and I came out convinced I had built something closer to an instrument. The interesting work was never predicting a size. It was deciding what the system is allowed to claim, when it has to abstain, which contradictions it must refuse, and how it proves each answer after the fact. When I flip that dropdown from the rigid jean to the stretch one and watch the correct size change under a body that did not, the thing I feel is not "the model is smart." It is "the physics is real, and we finally stopped hiding it behind a picture." You can flip that same dropdown at https://veriprajna.com/demos/ai-fit-prediction-fashion and watch it happen.

And if you would rather see it than read me describe it, here is the whole thing running end to end.

The question I keep turning over, and the one I would genuinely like other builders to argue with me about, is where else we are papering over a mechanical fact with a prettier image. Fashion reached for better pictures for a decade while the answer sat in a strain calculation any engineer could unit-test. So in your own domain, what is the mechanical fact underneath the thing everyone keeps trying to render, and would you trust a picture of it over a number you could check?

Related Research

Build Your AI with Confidence.

Partner with a team that has deep experience in building the next generation of enterprise AI. Let us help you design, build, and deploy an AI strategy you can trust.

Veriprajna Deep Tech Consultancy specializes in building safety-critical AI systems for healthcare, finance, and regulatory domains. Our architectures are validated against established protocols with comprehensive compliance documentation.