Forkcast
Chapter 2 — making the boundary the product
A decision engine where every displayed figure is a typed claim that must round-trip to a simulation field, and a generated paragraph containing one unsupported number is discarded whole.
- Trials per plan
- 500
- paired, common random numbers
- Tests
- 190
- zero build warnings, warnings-as-errors
- Domains on one engine
- 2
- electric depot and GPU compute hall
- Verified claims in the shipped decision
- 8
- 0 unsupported numbers
Figures with a dotted underline carry their source. Hover one to see whether it was verified in code or reported in project documentation.
Context
The situation
DepotOps proved that simulated futures make an operational decision legible. It also exposed the real risk: the moment a language model narrates those numbers, it can produce one that never came from the engine.
The problem
A model will confidently write “87% on-time” and “£4,200 saved”, and those figures come from nowhere. A wrong number that reads fluently is worse than no number at all, because someone acts on it. Prompt instructions do not fix this — nothing checks them.
What I built
Make provenance a type. Every displayed figure is a Claim carrying the simulation field it came from, how it was calculated, the seed and the trial count, and it is Verified only if it still round-trips to that field. Generated prose is then scanned number by number against the claim set. One unsupported figure discards the whole paragraph and the deterministic summary is shown instead.
When an operational site breaks, the hard part is which response to take in the next ten minutes. Modelling both options properly takes longer than the decision window, and asking a language model produces fluent figures that come from nowhere. Forkcast splits the problem along the line where each tool is good. A deterministic engine runs 500 paired Monte Carlo trials per response plan, and every figure on screen is a typed claim carrying its source field, calculation method, seed and trial count. The model writes the explanation; a verifier then scans every number in that prose and discards the paragraph if one of them is unsupported.
Architecture
How it fits together
Generated explanation
Reprioritising lifts on-time departures to 97.2%, leaving 1 of 20 at risk and avoiding £4,200 of penalties.
→ paragraph rejected · the deterministic summary is shown instead
- Incident textinput
in the operator’s words
- Structured extractionlanguage model
model reads into a schema
- IncidentComposerguard
clamps to a site that can exist
- Simulationdeterministic
500 paired trials per plan
- Claim setdeterministic
each figure round-trips to its field
- Generated proselanguage model
model writes the explanation
- Claim verifierguard
scans every number
- Recommendationoutput
or the deterministic summary
Key decisions
The choices that shaped it
- 01
Claims, not values
A figure is not a number on a screen — it is a typed object carrying the field it came from, the calculation that produced it, the seed and the trial count. It is Verified only if it still resolves to the simulation output it names. Edit the value and verification fails.
ClaimSetBuilder.Resolve
- 02
Rejection, not correction
When the verifier finds one unsupported figure, it discards the entire paragraph rather than patching that figure. A narrative that got one number wrong is not evidence about the others, and silently repairing it would hide the failure that matters.
ClaimVerifier
- 03
Identifiers and clock times are not quantities
The verifier masks vehicle identifiers and clock times before checking, so “18:40” and a unit number are never treated as figures needing support. Getting this wrong would either flood the output with false rejections or force the allow-list wide open.
Clock_times_and_vehicle_identifiers_are_not_treated_as_quantities
- 04
Common random numbers
Both response plans are evaluated against the same sampled nights. The gap between them reflects the plans, not sampling noise, so one plan cannot look better by accident.
- 05
SplitMix64, implemented in-tree
The generator is written in the repository rather than taken from System.Random, so anyone can regenerate the published figures from the published seed on any platform. A test pins a derived seed literally, to catch that ever changing.
Derived_seeds_do_not_depend_on_runtime_string_hashing
- 06
Two domains, one engine — asserted by test
An electric depot and a GPU compute hall share no vocabulary, units or failure mode, and run on identical simulation, comparison, claim and recommendation code. The vocabulary is data. Tests assert that neither domain’s critical-constraint string contains the other’s nouns, so “it generalises” is a property rather than an adjective.
The_critical_constraint_speaks_the_domain_language
- 07
Two languages, and provably one arithmetic
English and French are hand-written text packs rather than runtime translation, precisely so no model is ever in a position to translate a number. The verifier is taught to read the forms the French ledger prints — a checker that could not parse its own output would report the product’s own figures as invented.
A_french_run_and_an_english_run_are_the_same_simulation
Evidence
What it actually looked like

Every number, accounted for. Expand any claim for its source field and calculation.
Interface
Two futures, on one shared scale, so the plans can be read against each other.
Interface
Try to fool it: every number in a submitted paragraph gets a verdict.
InterfaceMeasured
Every figure, with its source
- Trials per plan
- 500
- paired, common random numbers
- Tests
- 190
- zero build warnings, warnings-as-errors
- Domains on one engine
- 2
- electric depot and GPU compute hall
- Verified claims in the shipped decision
- 8
- 0 unsupported numbers
- Published seed
- 20260728
- reproducible on any platform
Figures with a dotted underline carry their source. Hover one to see whether it was verified in code or reported in project documentation.
Recognition
Result
~100 participants
Awarded for the most impressive individual project.

Best Solo Hacker — most impressive individual project. Microsoft HQ, 29 July 2026.
AwardThe result is context. What the system does, and how it was measured, is everything above this.
My contribution
Sole author — engine, verifier, API, interface, tests and the submission film.
What I owned
- Deterministic simulation engine with an in-tree SplitMix64 generator
- The claim layer: typed claims, resolution, and round-trip verification
- The claim verifier, its allow-list, and the public probe endpoint
- A second domain proving the engine is not shaped like the first
- Bilingual output where the arithmetic is provably identical across languages
- Minimal API, React interface, 190 tests, and the evidence-synced decision film
Stack and limits
Built with
- C#
- .NET 9
- ASP.NET Core Minimal API
- xUnit
- React
- TypeScript
- Vite
- Azure OpenAI
Techniques
- Typed claim provenance
- Post-generation claim verification
- Common random numbers
- Deterministic PRNG (SplitMix64)
- Constrained extraction into a clamped schema
- Domain vocabulary as data
What it is not
- The simulation is decision-support, not physics: no charge curves, no thermal model, no degradation.
- Operational data is synthetic, and the interface says so on the situation card.
- It compares two named strategies head to head. It does not search for the best one.
- The verifier checks numerals, not claims about causation. A paragraph can pass and still be misleading in its wording.
What carried forward
The second domain was the point. Once a GPU compute hall ran on the depot’s engine without a line of change in the simulation, the comparison or the claim layer, it was clear the valuable asset was never the depot model — it was the verified decision loop around it. That is what FleetMind builds on.
Next
Chapter 01
DepotOps
At 18:40 a charger fails. The agent simulates tonight two hundred times, finds that most of them end badly, and evaluates five interventions before anyone notices.
Explore case study→Chapter 03
FleetMind
Two prototypes converged into one product direction. Simulate the operational night, verify every figure, and give the operator a decision they can question and override.
Explore case study→