OrionFlow
Research · 2026

A verified data factory for CAD

A text-to-CAD model is only as good as the data it learns from. So we stopped looking for CAD data and started manufacturing it — and we refuse to keep a single part we haven't proven correct.

OrionFlow Research8 min read

The hard part of text-to-CAD is not the model. It's the data. There is very little clean, parametric CAD in the open, and most of what exists is dead geometry — meshes and STEP files with the design intent already stripped out. You can train a model to imitate the surface of a part from that. You cannot train it to reproduce the reasoning that built the part, because the reasoning was thrown away before the file was ever saved.

So we took the opposite position. Instead of harvesting whatever CAD we can find and hoping it teaches intent, we generate CAD we fully control and verify every piece of it before it earns a place in the corpus. A data factory, not a scraper. This note is about how we think about that factory — why it exists, why it runs on FreeCAD, and what "verified" actually buys us.

What we want the model to learn

We don't want a model that emits a shape. We want a model that reasons the way an engineer does: choose datums, express every dimension as a relationship, predict what the finished part should measure, and then check its own work. If that's the behaviour we want out, that's the behaviour the data has to carry in — the answer alone isn't enough.

So every record is built from a Blueprint: a part described entirely as expressions over named variables, with no magic numbers anywhere. A wall thickness is (od - id) / 2, never 3.0. The design intent lives in the relationships between dimensions, and those relationships are exactly what we want the weights to absorb.

Why no magic numbers

A constant teaches a model to memorise one part. A relationship teaches it to design a family of them. Freezing every dimension as an expression is what turns a dataset of shapes into a dataset of reasoning.

Why we build it in FreeCAD

To manufacture data at scale, we needed a CAD engine that is five things at once: open and scriptable end to end, able to run headless across many workers, deterministic, backed by a real B-rep kernel, and free to run tens of thousands of times. Only one option is all five, and it's FreeCAD.

The alternatives each fail on at least one axis:

  • Commercial and cloud CAD (Onshape and friends) have excellent kernels, but they're API-metered, license-gated, and cloud-bound. You can't cheaply build a solid a million times, and you can't ship the toolchain alongside the dataset so others can re-verify it.
  • Code-CAD libraries like build123d are superb for code-native parts, and we compile to build123d as a second backend — but a library is not a full parametric document. It has no sketch-constraint history, no native feature tree, none of the editable structure an engineer actually manipulates.

FreeCAD gives us the OpenCASCADE kernel for free, a scriptable headless process we can fan out across workers, and a native PartDesign history with real sketches, constraints, and feature order. Crucially, it also gives us the same failure modes a real engineer hits — boolean failures, self-intersections, walls too thin for the kernel to resolve. Those failures aren't noise to be filtered out. They're some of the most valuable signal we have.

FreeCAD is a backend, not the source of truth

Our intermediate representation is kernel-independent — a FeatureGraph that compiles to FreeCAD and build123d alike. FreeCAD is the forge where we build and verify at scale, not the format we're locked into.

How the factory works

The loop is deliberately simple, and it runs the same way for every part: Blueprint → build → verify → keep or repair.

The build step turns the frozen Blueprint into a solid in FreeCAD. The verify step is where the discipline lives — a part is admitted only if it passes its own frozen assertions, checked at three tiers:

  • Closed-form exact — volume and extents matched to the governing expression to within one part in a million.
  • Mesh-converged — quantities that have no closed form, checked to a tight tolerance with demonstrated convergence, so the number is real and not an artefact of a coarse mesh.
  • Measured-bounded — properties we can bound but not solve exactly, held inside a proven envelope.

When a part fails, we don't throw it away. We capture the whole episode — failure, diagnosis, fix, and re-verification — as a repair record. A model trained only on things that worked never learns to recover; a model trained on repairs learns to debug its own geometry.

Diversity is enforced by construction, too. Each part gets a topology signature, and a per-signature cap stops the factory from stamping out twenty-five thousand near-identical plates. A supervisor relaunches the run with fresh seeds to keep exploring the long tail of shapes rather than saturating the easy ones. The result is a Blueprint that reads less like a script and more like a specification with its own acceptance tests:

PARAM od, id, t
DERIVE wall = (od - id) / 2      # intent, not a constant
DERIVE V    = pi*(od/2)**2*t - pi*(id/2)**2*t

BUILD  tube from od, id, t
ASSERT wall  > min_wall          # precondition, tier 1
ASSERT volume == V   rel 1e-6    # closed-form, exact
ASSERT extent_z == t rel 1e-6    # measured vs expression

Only if the built solid satisfies every assertion does the record — reasoning and all — enter the corpus.

What we have so far

Running that loop gives us a corpus where every row is either provably correct, or a provably-correct fix of something that wasn't:

CORPUS  corpus_v3_scale.db  (SQLite, source of truth)
        42,723  verified records
        25,000  clean synthetic parts
         3,126  distinct verified topologies
           700  real-CAD topologies preserved
        ~17,000 repair records (failure -> fix -> re-verified)

TRAIN   rl_corpus_v3_scale.jsonl
        85,342  packed rows
                - reasoning traces (plan + derivation + check)
                - stepwise sequences with per-assertion reward
                - preference pairs (verified vs. faulted)
                - repair pairs (natural failures weighted 3x)

        frozen, checksummed, and backed up off-machine

It's not a large dataset by web-scraping standards, and it isn't meant to be. Every one of those rows was built, measured, and checked against its own definition of correct. That's the trade we're making: not the most CAD we can gather, but the most CAD we can trust.

What's next

The factory works and the corpus is frozen. The next step is the reason we built any of it — fine-tuning a model on this data, and then closing the loop: feeding the model's own failures back through the same verify-and-repair machinery, so the factory grows exactly where the model is weakest.

That's the subject of the next note in this series. We'll cover the training setup, what the verified data does to a model's behaviour, and the first results — once the model is trained.

To be continued — the fine-tuned model and its results will be added here as they land.

Related: A kernel-independent IR for editable CAD →

← All research