A domain and its deployment are usually written together, so a new place to run means editing the domain. This one was not: a Tetris board was held fixed while five stagings and six clients were built around it, and the evidence is not an argument but a diff — over the domain directory, across fifteen commits, coming back empty.
Watch the demoA Tetris board and its rules — one domain directory
Domain edits0
Five stagings: a console, two browser transports, two co-hosted actors, three container peers
six clients, human and automated
Architectural question
Can a domain stay unchanged while everything about its deployment changes — where it runs, how its input and output travel, and who observes it?
What is being measured
A Tetris game, whose board and rules are a small but complete domain: a Well and a set of operations over it. Around it, one actor and twelve host projects — a console, a browser over WebSocket, a browser over REST and server-sent events, an automated player, two observers, a server, three stage hosts including one over TLS, and an input host. Sixty-six files. The domain declares no interface for what drives it or for what it emits, so there is nothing for a staging to implement.
The evidence is a diff
Not a claim about the code — a command over its history, in the repository the example was written in.
- The domain's last commit is fd8d94b.
- Three of the stagings were added on 23 July, twenty-four days later.the gap is the point — they came after, not alongside
- Fifteen commits separate the two.
- git diff fd8d94b..main -- Tetris/domain/ comes back empty.the whole result, in one line a reader can run
Zero test doubles, too, and that is a separate fact: the domain asks for nothing to be stood in for, so there is nothing to fake in order to test it.
The comparison the argument rests on
An orthodox ports-and-adapters version of the same game was built for the comparison, so the difference would be measured rather than estimated. Its eleven rule files differ from this domain's by one line each — the namespace — so the comparison is not won by writing a worse opponent. It is published whole and builds on its own: checked here, it compiles clean and its suite passes 64 of 64.
- Three driven ports — board output, piece selection, state — against none here. With them come three stand-ins, and without those, 20 of 64 tests do not run. Counted here: the twenty are the two files that touch the stand-ins, and the remaining forty-four never mention them.
- A reconstitution surface of its own: 56 lines added and 5 removed inside the rule model, against none here, because replay re-enters through the operations the acts were performed through.
- The lab's own README calls the 56-line figure the most attackable in the paper, and names the two files to read before running anything.
Two of the four claims that lab was built to check came back refuted and one tied, and the difference that survived is not the one the estimates predicted. It is described by its own author as correcting the paper more than confirming it — which is the reason to trust the figure that did survive.
And when the domain did grow
The converse measurement: a score and a difficulty level were added — 98 lines, of which 30 are code. All twelve hosts kept running with no edit, verified by running them before and after rather than by compiling them. Adopting the new capability then cost something only where it was wanted, and it divides exactly.
| Hosts | Lines each | |
|---|---|---|
| Needed nothing at all | 4 | 0 |
| One line | 5 | 1 |
| The two browser hosts | 2 | 4 |
| The input host — the only place the level changes what happens | 1 | 32 |
That last row is the boundary the whole arrangement predicts, showing up where it was expected: the domain owns what level the game is at, the staging owns how fast gravity ticks, and the domain still holds no clock.
The finding nobody was looking for
Three of eight replay fixtures did not fail. They answered. A game recorded as having cleared twenty rows replayed as having cleared two; one recorded at six replayed at four; the third, recorded at zero, replayed at zero — correct, and therefore invisible in exactly the numbers a reader checks.
The cause was a defect in the substrate's index, since fixed upstream, and this lab was one of two independent reports that found it. The rule outlives the fix: a replay checked only for its own internal consistency will pass while being wrong, so the lab now carries the state recorded at play time and asserts the replay against it.
What it does not establish
The paper states its own limits before anyone else can, and the first is aimed at the number this page leads with.
- An empty diff is gameable by construction. Any code can be held constant if all the variation is pushed outside it, and the same empty diff is equally consistent with a domain designed backwards from a known set of stagings. The stagings were written by the domain's own author.
- It is not a resilience result. No peer was killed and no partition induced, so partial failure is untouched.
- It measures invariance under staging, not under evolution — what happens when the domain is deployed differently, not what happens as the domain changes over years.
- It is an existence proof that the separation is buildable. It is not a cost or performance evaluation, and it does not say the arrangement is cheaper.
Run it yourself
Nine laboratories, published with the paper under Apache 2.0. Each stands alone — none depends on another having been run, and none leaves state another consumes.
- If you run only one, run the ported-baseline lab. It needs nothing but .NET, carries the comparison whole, and builds standalone.the number to check hardest
- The diff above is seconds long and builds nothing. Its output is captured for a reader who would rather not clone anything.the one lab a vendored copy cannot carry — it is a claim about a history
- The growth lab runs the twelve hosts before and after the domain changes: 14 pass, both times.
One trap, stated where a reader meets it: the diff measures that the domain did not change, while two of the labs change it on purpose. Running the diff on their branches reports a difference correctly — that is a different measurement, not a failed one.