EngineeringDeep dive

Ten thousand worlds before the first real fitter

TyreStack's scheduler had no customers yet, so before launch we built an audited oracle and threw ten thousand generated worlds of bookings, holds and late vans at it, comparing the old engine and the new one call for call.

10,000 set large on a black background beside a terminal window summarising the oracle test: ten thousand worlds built and compared, zero differences, a 92.97% mutation score, and 502 bookings lost when one real fix was deliberately undone, above the words: Ten thousand generated worlds before the first real fitter
10,000generated worlds the rewritten engine had to match exactly
92.97%Stryker mutation score on the five riskiest files
502bookings the sweep caught itself losing when one real fix was undone
0paying customers signed when the ten thousand worlds ran

On 2 October 2026 our fitting scheduler got a second engine. Not a feature: a twin, rewritten in TypeScript from the same rules as the JavaScript prototype we had already checked by hand, line by line, months earlier. The only honest way to know the twin behaved exactly like the original was to stop checking by hand and build something that could check thousands of times faster than a person ever could.

That mattered because nobody was going to be forgiving about it. TyreStack’s scheduler had not taken a single real booking from a real customer. There was no fitter to notice a wrongly booked Tuesday, no receptionist to complain that a promise got broken. Whatever caught the rewrite’s mistakes had to do it before anyone depended on the thing at all.

The old engine still gets the last word

The already-checked prototype became what the test files call the oracle: the version everyone agrees is right, used to grade everything else. Twenty-two of its intended differences from the new port are written down and tested on their own (a Sunday closed under the old rules, a collection taken outside the supplier’s hours, and twenty more), so a pass could not quietly mean the hard part had been left unchecked. Anything else that differed would be a bug in the rewrite, full stop.

Checking two engines agree on a handful of examples is a morning’s work. Checking they agree on everything the real desk could throw at them is not. So the test uses fast-check, a property-testing library, to build a fresh fabricated business for every run: one to three vans, zero to twelve jobs, ten different times of day, up to three extra jobs of varying size and urgency, another desk’s hold on a slot, a van taken off the road for the day or half the day, a van running twenty minutes to two and a half hours late, and, in about one world in ten, the day’s driving limit turned down on purpose so the refusal that guards it actually gets exercised. Each generated World is then driven through one of five commands, placing, moving, cancelling, releasing a job, or just running the clock forward.

fast-check picks a recipeabout 20 knobs: vans, jobs, holds, a late van, the driving limitone generated Worlda fabricated tyre business, seeded and deterministicTypeScript portsrc/index.ts, the rewriteaudited oraclethe legacy engine, frozen before the rewrite begansame call, compared as datadropCheck, suggest, check, place, move, cancel, needsmatch: next Worlddiffer: stop, show the diffRepeated 10,000 times, seed 20261002, about 77 seconds in all.
Every one of ten thousand generated worlds goes to both engines and is compared as data, not as rendered text. The first difference stops the run and names the call that disagreed.

On seed 20261002 that built and compared 10,000 of those worlds in 77 seconds flat, and found zero differences. Between them, the two engines were asked dropCheck, the call that decides whether a slot can take a job, 38,968 times; check, 25,026 times; the day’s own layout, dayOf, 19,759 times; and suggest, the one that offers a customer a time, 9,742 times.

the oracle test, seed 20261002

run the oracle test

building 10,000 worlds

port and oracle, call for call

10,000 worlds compared in 77 seconds

0 differences

Condensed. The seed, the world count, the time and the result are from the logged run.

What ten thousand worlds called

Every call ran against the rewrite and the oracle side by side; a mismatch would have stopped the run.

dropCheck, can this job go here38,968check, is this slot still open25,026dayOf, a van’s whole day19,759needs, what wants attention10,000suggest, offer the customer a time9,742cancel2,496

Source: fitting-scheduler oracle test log, 2 to 7 October 2026

Seven promises, checked on every drop

Agreeing with an old prototype proves the rewrite is faithful. It does not prove the rules were ever right. A second kind of generated test, the sweep, checks that directly: for every place, every job size, every time of day and every fitter, does the engine keep seven plain promises? Every job that fits books at the time it was offered. No customer’s promise gets worse because someone else booked. Nothing is offered before the business’s own lead time. Every refusal gives a short, plain reason. Checking whether a job fits never changes anything. Nothing is ever booked outside a van’s hours. And the same question, asked twice, gets the same answer.

Under the old hours, the sweep tried 43,200 drops across 900 of these worlds, 14,473 of them fit, and all 14,473 booked. Under the newer, longer hours it tried 83,700 drops, 45,895 fit, and all 45,895 booked, 2,189 of them collecting tyres after the supplier had shut for the night. Zero failures, either way.

A test that never fails is only reassuring if it is capable of failing. So one fix is deliberately undone: a van waiting for its next window used to take its break during the wait; the reverted version waits first and takes the break afterwards, which can refuse a booking the engine had already offered, or leave an earlier promise worse off. Run the same sweep against that broken copy and it does fail, loudly.

502bookings the sweep refused once that one real fix was undone, in worlds where every job should have fit. The real engine, same sweep, same worlds: all of them booked.

A third kind of check runs underneath both of these. Stryker changes the engine’s own logic by one small mutation at a time, a rule flipped, a boundary moved by one, and the test suite has to notice. Against the five files most likely to hide a mistake, it noticed 92.97% of the time when the release was tagged: 898 mutations killed, 1 timed out, 62 survived and 6 were never even reached, in 36 minutes 27 seconds. It had scored 93.45% when the rewrite itself was finished, so the extra product work the audit demanded afterwards did not quietly loosen the net.

That is why TyreStack’s own platform, when it later imported this scheduler whole, left the engine untouched and built its own layer of bays, stock and service rules on top instead. The decision log is blunt about the reason: the engine was proven equal to its oracle on ten thousand worlds, and editing it would void that proof.

We had no fitter to test it on

A sceptical engineer would say property tests are a trick for software with no users yet, and that a week of real fitters booking real jobs would have found more real bugs than any generator. That is fair, and it is also exactly our situation: when this testing ran, TyreStack had not signed a single customer. The order form, the terms of service and the data processing agreement were still being finalised before anyone could sign them. A couple of weeks later, when the same Google Cloud zone failure that took other products’ databases down reached our production tyre-lookup service too, the decision record said plainly why nobody panicked: the only traffic it had seen that week was our own test calls.

Wait for a real fitterNot available

There was no customer yet to wait for, and a rewrite cannot sit idle until one appears.

Hand-check a dozen examplesRejected

The engine answers several kinds of call on a day with up to three vans, a dozen jobs and any mix of holds, time off and a late van. A person checking by eye would need hundreds of tries to reach the refusals the generator found in minutes.

Generate thousands of fabricated days and let the computer compareChosen

fast-check built 10,000 fabricated tyre businesses and ran the port and the oracle side by side on each one, throwing on the first disagreement. 77 seconds did what no amount of hand-checking could.

We did not treat the generated worlds as the only gate, either. A later audit put the scheduler in front of blind test runs and four critics playing a receptionist, a designer, an accessibility reviewer and a reliability reviewer, and that caught findings the worlds never could.

What ten thousand worlds never imagined

A generator only varies what someone wrote into its recipe. Ours varies vans, jobs, holds, a late van and a tightened driving limit, because those are the things a fitting business changes from one day to the next. It has never varied a van’s equipment changing after a job is already booked on it, because nobody had written that into the recipe. A week earlier we had tried a related idea on a puzzle game: a bot driving it through real touch events.

That gap showed up for real, just not from a customer. The same audit’s reliability critic found that a job left booked on a van could carry on looking perfectly fine even after that van’s equipment, or the tyres it needed, moved somewhere else, and the same silence held when the business’s opening hours shrank with jobs already on the books. All three were rated high severity, and all three were fixed with one change and a new set of tests that list exactly which booked jobs no longer fit where they sit. Ten thousand generated worlds, agreeing with an audited prototype on every call, had nothing to say about any of it, because the prototype never modelled it either, and the recipe never asked.

So the honest answer about what surprised us once this met the real world is that nothing has, yet, because nothing real has met it. No fitter had booked a real job through this engine when the worlds ran, and none had by the time the lookup outage put that fact in writing. The nearest thing we have to a real surprise came from people pretending to be a receptionist and a fitter for an afternoon, reading the same screens a prototype never had to defend. That is a weaker test than a real customer, and we know it.

Where the numbers come from

  1. fitting-scheduler engine oracle test and its log output, 2 to 7 October 2026 (the port against the oracle, fast-check, seed 20261002, 10,000 runs).
  2. fitting-scheduler engine sweep tests and their log output, including the idle-break mutant, 2 to 7 October 2026.
  3. fitting-scheduler README and release notes, 7 October 2026 (quality bars, mutation score, gate steps).
  4. fitting-scheduler audit ledger, the reliability findings about equipment and hours changing after a job is booked.
  5. TyreStack decision log, the entries recording why the scheduler was imported and never edited.
  6. TyreStack decision log, 20 October 2026, on the production lookup outage (no fitter or customer traffic on it that week).
  7. TyreStack task tracker, the task for finalising the order form before the first client signs.

Edward Clarke, Director. A decade of website development, testing and customer success. Builds our client sites.