Worker thread
The engine, materials, water, fire, air, creatures and tools, and the seven WebAssembly kernels.
Game Tailors
Source: How we keep it right
The drawing app where the paper is real. No ads. No accounts. No personal data: only anonymous counts, which you can switch off.
Game Tailors · Schieweg 15Y-40, 2627 AN Delft (NL)
KvK 92437702 · VAT NL866044474B01
info@gametailors.com · +31 6 4227 5919
© 2026 Game Tailors
How we keep it right
Honey poured on a drawing today should behave as it did yesterday. Behind Professor Oops sit thousands of automatic checks that do what children do: pour paint, bring a hammer down, set a fire, wait for mould. Then they look at the page. The promises a family cares about, such as "no animal is ever hurt" and "no ads", are written down as checks too, so breaking one fails the run.

At the release, the code held 270 test files, holding 2,614 tests and 8,933 individual checks. That's 56 lines of test for every 100 lines of game. The next update has 353 files and 60 lines for every 100 next update. The tests grew faster than the game: on the second day of building they were 12 % of its size.
Most of them aren't the usual small checks on one function. Many set out a real page, work a real tool on it, run the simulation for a few seconds and read what happened. Their names are sentences you could check at a kitchen table: "a slap squashes a tomato but not a banana; a slammed rolling pin bursts an orange but not an apple". About two in three test files step the real engine.
In a test, the simulation moves in fixed steps, usually a sixtieth of a second, never by the clock. So a busy computer gets exactly the same answer as a quiet one. A fast tier leaves out the 700 or so tests that take more than a second, for use while working. The full run adds a type check of every file, a production build and a browser run in Chrome.
Here is a seam, shown plainly. The checks run on our own computers. There's no separate build server that refuses a release, so keeping a failing change out of the game is a working rule we keep by hand. Real phones and tablets are tried by hand too: the automated runs use a desktop Chrome, plus one test of the purchase flow on an iPhone simulator.
From 18 Oct to 5 Nov the game source grew from 21.3 to 119.5 thousand lines, and the tests from 2.5 to 72.1 thousand.
| date (2026) | game source | tests |
|---|---|---|
| 18 Oct | 21.3 | 2.5 |
| 20 Oct | 35.7 | 7.7 |
| 22 Oct | 48.6 | 20.2 |
| 24 Oct | 71.6 | 33.9 |
| 26 Oct | 85.9 | 44.4 |
| 28 Oct | 86.1 | 45.5 |
| 30 Oct | 99.4 | 54.4 |
| 1 Nov | 106.9 | 60.7 |
| 3 Nov | 118.2 | 69.1 |
| 5 Nov | 119.5 | 72.1 |
Source: Lines of game and test code, counted on one version a day; after 2 Nov the numbers are the next update's.
The busiest loops of the simulation exist twice. These are where goop flows, paper soaks, fire spreads, a hand bulldozes paint and the air finds its pressure. One copy is readable TypeScript. The other is compiled to WebAssembly with SIMD, so a cheap tablet keeps up. The tests run the readable copy and the apps run the compiled one, so the tests only speak for the apps if the two agree.
Three layers hold them together. First, each compiled kernel names the exact functions and constants it copies, and the build stores a fingerprint of their source. Change one line of a copied loop and the test run fails, naming the function, until its twin is ported and someone has recorded that they checked it. Comments and spacing don't count; the code does.
Second, each kernel runs a set of test pages twice, with and without it, and every field of every cell is compared. For goop, fire, the bulldozing hand, soap on milk and the air's pressure solve, each tested on its own with the other kernels off, the answer must match to the last bit. They manage that by doing their sums in the same order and the same precision as the readable copy. The paper and floating-layer kernels use 32-bit lanes for speed, so they're held to a small tolerance instead: one part in 100,000 for paper, one in 10,000 for the floating layer.
Third, one page with every material on it runs with all kernels on and with all off, on six page shapes, and must agree within a stated tolerance. If the kernels can't start on a device, the game falls back to the readable loops, and a test checks that this gives exactly the same goop and wetness as the readable engine.
Two seams, shown plainly. On one tilted page, six cells along the bottom row drift up to 3.4 parts in 10,000 between the paper kernel and its twin. The test is written to expect that failure, so it will fail the day someone fixes it and force them to make it a normal test next update. And on lower detail settings the readable air does a cheaper pressure solve, while the compiled air always does the full one. The parity test sets them equal first. In the apps the wind at those settings is the fuller one, on purpose.
Left, the readable loop; right, its copy. Both run the game's paper-wetting rule on the same 64 × 48 cells, with drops landing every second or so. Cells where the copy differs from the original in even one bit turn red. A fingerprint shows as its 32-bit number. What to look for: with the same sums in the same order, the two fingerprints match exactly, forever. Add the same numbers in another order, or do the sums in 32-bit floats as SIMD lanes do, and the fingerprint breaks at once, though the cells stay very close: hundred-millionths apart for another order, millionths for 32-bit sums. That's why the game holds five kernels to the bit, and paper and floating layers to a tolerance. The clock runs 3× fast.
Five kernels must be identical; paper may differ by 1e-5, the floating layer by 1e-4, the whole page by 2e-3. The known gap is 3.4e-4, and one 32-bit rounding is about 6e-8.
| rounding | 5 exact | paper | known gap | float | whole page | |
|---|---|---|---|---|---|---|
| rounding | 60 | |||||
| 5 exact | 1 | |||||
| paper | 10 000 | |||||
| known gap | 340 000 | |||||
| float | 100 000 | |||||
| whole page | 2 000 000 |
Source: Allowed or seen differences between each compiled loop and its readable twin. Known gap: 3.4e-4 seen in six cells of one tilted page, pinned as an expected failure next update. "Rounding": one 32-bit float rounding, about 6e-8, for scale. The measures differ, so compare each on its own, not across.
Some test pages are pinned. A busy page is worked by a whole set of tools, and at the end its fields are boiled down to an eight-digit fingerprint. If paint, water or oil end up different on that page, even in one cell by one bit of the fields it covers, the fingerprint changes and the test fails.
Behaviour does change on purpose. Then the fingerprint is updated, and the note beside it says what moved and why, often with what the fingerprint would be with the new behaviour switched off. Over the life of these files, 108 of the 112 changes to a fingerprint came with a note in the same change. Read in order, the notes are a logbook of the game's physics: "a pigment's grains ride the water's flow to a drying edge".
A fingerprint says "as before". It can't say "right": that's what the scene tests are for. And they mostly check behaviour a child would recognise, not real-world figures.
The same idea, to the bit, guards several promises that are easy to break by accident:
Recorded play, replayed from a saved moment, ends on exactly the same page. Without the recorded random numbers and clock it goes another way, and the test checks that too.
A time skip gives the same page at three detail levels, each with its own work budget.
Opening the measuring panel changes nothing on the page.
The picture data sent tile by tile is exactly what packing the whole page afresh would send.
Undo by small differences puts back exactly what whole copies did.
Mirror the page and the wind mirrors, to the bit.
The tests' own hash. A small page of paint, 40 × 30 cells, boiled down to a fingerprint with the same FNV-1a hash the pinned tests use. One cell, ringed in red, already differs from the pinned page by the smallest step a 32-bit number can take, about one part in ten million. What to look for: the picture can't show it, yet the fingerprint is a quite different number and the pin fails. Tap the ringed cell, or press Put it back, and the pin passes; tap any other cell to change that one.
The simulation runs in a Web Worker, a separate thread, so drawing and touch stay smooth while the page is worked out. The screen's side sees a copy of what it needs to draw. The split has one nasty trap. Screen code that reaches into the engine directly still works when everything runs on one thread, and silently does nothing in the worker. "It has happened four times," says the test that now stops it.
That test reads the screen side's source with the TypeScript compiler and lists every value it takes from the engine's side. Each must be on a list with a reason: a constant, a pure function, a class whose copy lives on the screen side, or state the two share on purpose. A new one fails the run with a message saying where it belongs. The test also checks that it notices a new import, so it can't quietly go blind.
A browser run covers what code reading can't. It opens the real game in headless Chrome twice, with the simulation in its worker and in the same thread, and runs the same checks in both. Sand jumps on a speaker. Sliders reach the simulation. A saved picture is a real 3200-pixel JPEG. A colouring page loads. A line of scenes runs: a fat fire under a lid, oil on water, folded dough, a battery lighting a bulb. Every tool's name fits under its picture in every language. Each check is there because that thing "broke silently in worker mode once".
The engine, materials, water, fire, air, creatures and tools, and the seven WebAssembly kernels.
→ messages. Every touch, slider and button becomes a named call the worker handles.
← replica. A copy of what's drawn: 47 engine fields and 40 classes at release.
← textures. Only the changed tiles of the page, handed over, not copied.
allow list. Values the screen side may import, each with its reason: 198 in the next update next update.
Menus and buttons, the WebGL2 paper, the paintings and the creatures on it.
Checked by a test on every run
An import "works in-thread and silently does nothing in the worker".
Every engine value the screen side imports is on a list with its reason.
Checked by a test on every run
"Saved, or worked out again, or only for the moment."
Nothing new is quietly lost on undo, on reload or on its way to the screen.
Checked by a test on every run
A load-order error "once stopped the app in the browser".
Each simulation module, the engine and the tools load first, alone, in plain Node.
Checked by a test on every run
"Code-drawn objects kept coming back."
Any function that draws shapes or text must say why it isn't drawing an object: 92 at release.
Checked by a test on every run
A name written in many places drifts.
The source, configs, native projects and legal pages take it from one setting.
Pinned by a test
The manifest's comment calls it "a promise to families".
Android's merged manifest may ask for the internet and store billing; the advertising ID and storage permissions are removed.
Checked by a test on every run
App Store rule 2.3.1.
The page can't reach it by static import, and none of its files may grant, report or write a purchase.
Checked by a test on every run
next update Salt water split by a battery bubbles and turns sour and soapy, but the simulation makes no oxygen or chlorine.
"No word of the electrolysis, in the code or the catalogue, says oxygen or chlorine."
The simulation doesn't make a picture. It keeps a stack of numbers for every spot on the paper, each about half a millimetre across: how much colour has soaked in, how wet it is, how thick the ketchup lies, how hot and how charred. On every frame a small program on the graphics chip turns those numbers into a lit surface for each pixel on screen.
Colour is kept the way light passes through it. Each spot stores how strongly it absorbs red, green and blue, and the paper shows through as e to the minus that. Two washes over each other add their absorbance, so yellow over blue gives green, as glazes do. That's the Beer-Lambert law Swinehart 1962, which we found described our model after we'd built it, in three channels. Real paint also scatters light Kubelka 1931; the game leaves that out.
The paper has real relief. A dent from a pencil pressed hard, the raised outline of a colouring page, the waves wet paper dries into, a dollop of ketchup and a puddle on top all add up to one height. The light reads that height to shade slopes, cast short shadows and darken hollows. The water reads the same dents and outlines, so by the code it runs into a groove and stays inside a raised line. A pencil groove is shallow, though, and in the game neither it nor water running into it shows. A blob of ketchup or thick paint shows its relief plainly.
Shine follows the height too. A glossy surface throws the lamp back only where it tilts toward it, so a big, flat puddle has almost no highlight in its middle, and its edges and ripples shine. A single pour soaks in within a second or two, before it can show that. Wet paper gets darker, and only paper soaked right through starts to shine.
The paper's grain is noise made once for each sheet: a fine tooth plus longer fibres. Wet paper waves up as it soaks and never quite flattens again as it dries, because its waves stop shrinking at a low floor instead of going flat. An iron or a rolling pin presses them flat. Burn a hole and the painted wooden table shows through.
A corner of the page, 120 × 80 cells, lit by the game's own formulas: the same height sum, key light, shadow march, occlusion and shine. Water has just been poured on a pressed groove, with ketchup and honey nearby and a colouring page's raised outline. Pick something and drag on the paper, or press Add it, or pour again. What to look for: the water levels out, fills the groove and soaks in within a few seconds; the wet paper stays darker and waves up as it dries. The middle of the honey stays dull while its rim shines. Turn shadows or shine off to see what each adds, and fewer shadow steps to see what a slow tablet gives up. In the game a pencil groove is too shallow to see, and we never saw poured water run into one.

Every highlight peaks at a 22.5° tilt toward the key light: 0.85 for water or honey, 0.77 for ketchup, 0.51 for mustard and 0.07 for dry paper.
| tilt toward the key light (degrees) | dry paper | mustard | ketchup | water or honey |
|---|---|---|---|---|
| 0 | 0.01347 | 0.00047 | 0.00003 | 0.00001 |
| 0.5 | 0.01449 | 0.00065 | 0.00005 | 0.00002 |
| 1 | 0.01556 | 0.00088 | 0.00008 | 0.00003 |
| 1.5 | 0.01668 | 0.00119 | 0.00012 | 0.00006 |
| 2 | 0.01784 | 0.00159 | 0.00018 | 0.00009 |
| 2.5 | 0.01906 | 0.00211 | 0.00028 | 0.00014 |
| 3 | 0.02032 | 0.00278 | 0.00041 | 0.00021 |
| 3.5 | 0.02162 | 0.00364 | 0.00061 | 0.00033 |
| 4 | 0.02297 | 0.00472 | 0.00089 | 0.00049 |
| 4.5 | 0.02436 | 0.00609 | 0.00128 | 0.00074 |
| 5 | 0.02579 | 0.00779 | 0.00183 | 0.0011 |
| 5.5 | 0.02726 | 0.00989 | 0.00258 | 0.0016 |
| 6 | 0.02876 | 0.01246 | 0.00361 | 0.00232 |
| 6.5 | 0.0303 | 0.01559 | 0.00499 | 0.00331 |
| 7 | 0.03186 | 0.01937 | 0.00682 | 0.00467 |
| 7.5 | 0.03345 | 0.02389 | 0.00923 | 0.00652 |
| 8 | 0.03505 | 0.02925 | 0.01236 | 0.009 |
| 8.5 | 0.03668 | 0.03556 | 0.01639 | 0.01229 |
| 9 | 0.03831 | 0.04293 | 0.02151 | 0.01658 |
| 9.5 | 0.03996 | 0.05146 | 0.02793 | 0.02212 |
| 10 | 0.0416 | 0.06125 | 0.03591 | 0.02917 |
| 10.5 | 0.04325 | 0.07238 | 0.0457 | 0.03806 |
| 11 | 0.04488 | 0.08495 | 0.05758 | 0.0491 |
| 11.5 | 0.0465 | 0.09901 | 0.07182 | 0.06264 |
| 12 | 0.0481 | 0.11458 | 0.08868 | 0.07903 |
| 12.5 | 0.04968 | 0.1317 | 0.10842 | 0.09863 |
| 13 | 0.05123 | 0.15033 | 0.13122 | 0.12173 |
| 13.5 | 0.05274 | 0.17041 | 0.15726 | 0.14861 |
| 14 | 0.05421 | 0.19186 | 0.1866 | 0.17945 |
| 14.5 | 0.05563 | 0.21453 | 0.21924 | 0.21434 |
| 15 | 0.057 | 0.23825 | 0.25505 | 0.25325 |
| 15.5 | 0.05831 | 0.26279 | 0.29381 | 0.296 |
| 16 | 0.05956 | 0.28789 | 0.33516 | 0.34223 |
| 16.5 | 0.06073 | 0.31325 | 0.3786 | 0.39144 |
| 17 | 0.06184 | 0.33855 | 0.4235 | 0.44292 |
| 17.5 | 0.06286 | 0.36342 | 0.46913 | 0.4958 |
| 18 | 0.0638 | 0.3875 | 0.51463 | 0.54907 |
| 18.5 | 0.06466 | 0.4104 | 0.55908 | 0.60157 |
| 19 | 0.06542 | 0.43172 | 0.60149 | 0.65207 |
| 19.5 | 0.06609 | 0.45112 | 0.64087 | 0.69929 |
| 20 | 0.06667 | 0.46822 | 0.67623 | 0.74194 |
| 20.5 | 0.06714 | 0.48273 | 0.70667 | 0.77884 |
| 21 | 0.06751 | 0.49435 | 0.73136 | 0.80889 |
| 21.5 | 0.06778 | 0.50287 | 0.74962 | 0.83118 |
| 22 | 0.06794 | 0.50812 | 0.76094 | 0.84502 |
| 22.5 | 0.068 | 0.51 | 0.76499 | 0.84999 |
| 23 | 0.06795 | 0.50846 | 0.76166 | 0.84592 |
| 23.5 | 0.0678 | 0.50354 | 0.75105 | 0.83293 |
| 24 | 0.06754 | 0.49534 | 0.73346 | 0.81145 |
| 24.5 | 0.06718 | 0.48401 | 0.70938 | 0.78213 |
| 25 | 0.06672 | 0.46978 | 0.67948 | 0.74587 |
| 25.5 | 0.06615 | 0.45292 | 0.64456 | 0.70373 |
| 26 | 0.06549 | 0.43374 | 0.60554 | 0.65691 |
| 26.5 | 0.06474 | 0.41258 | 0.56338 | 0.60668 |
| 27 | 0.06389 | 0.38983 | 0.51909 | 0.55432 |
| 27.5 | 0.06296 | 0.36585 | 0.47365 | 0.50107 |
| 28 | 0.06194 | 0.34104 | 0.42799 | 0.4481 |
| 28.5 | 0.06085 | 0.31576 | 0.38298 | 0.39644 |
| 29 | 0.05968 | 0.29039 | 0.33937 | 0.34698 |
| 29.5 | 0.05844 | 0.26525 | 0.2978 | 0.30042 |
| 30 | 0.05713 | 0.24064 | 0.25876 | 0.25732 |
| 30.5 | 0.05577 | 0.21684 | 0.22264 | 0.21802 |
| 31 | 0.05435 | 0.19405 | 0.18968 | 0.18272 |
| 31.5 | 0.05289 | 0.17248 | 0.16001 | 0.15148 |
| 32 | 0.05138 | 0.15225 | 0.13365 | 0.12422 |
| 32.5 | 0.04984 | 0.13348 | 0.11053 | 0.10075 |
| 33 | 0.04826 | 0.11621 | 0.0905 | 0.08082 |
| 33.5 | 0.04666 | 0.10048 | 0.07337 | 0.06413 |
| 34 | 0.04504 | 0.08627 | 0.05888 | 0.05032 |
| 34.5 | 0.04341 | 0.07356 | 0.04678 | 0.03905 |
| 35 | 0.04177 | 0.06229 | 0.03679 | 0.02997 |
| 35.5 | 0.04012 | 0.05237 | 0.02865 | 0.02274 |
| 36 | 0.03848 | 0.04372 | 0.02208 | 0.01707 |
| 36.5 | 0.03684 | 0.03624 | 0.01684 | 0.01266 |
| 37 | 0.03521 | 0.02983 | 0.01272 | 0.00929 |
| 37.5 | 0.0336 | 0.02438 | 0.0095 | 0.00674 |
| 38 | 0.03201 | 0.01978 | 0.00703 | 0.00483 |
| 38.5 | 0.03045 | 0.01594 | 0.00514 | 0.00343 |
| 39 | 0.02891 | 0.01274 | 0.00373 | 0.0024 |
| 39.5 | 0.02741 | 0.01012 | 0.00267 | 0.00166 |
| 40 | 0.02593 | 0.00797 | 0.00189 | 0.00114 |
| 40.5 | 0.0245 | 0.00624 | 0.00133 | 0.00077 |
| 41 | 0.0231 | 0.00484 | 0.00092 | 0.00052 |
| 41.5 | 0.02175 | 0.00373 | 0.00063 | 0.00034 |
| 42 | 0.02044 | 0.00286 | 0.00043 | 0.00022 |
| 42.5 | 0.01918 | 0.00217 | 0.00029 | 0.00014 |
| 43 | 0.01796 | 0.00163 | 0.00019 | 0.00009 |
| 43.5 | 0.01679 | 0.00122 | 0.00013 | 0.00006 |
| 44 | 0.01567 | 0.00091 | 0.00008 | 0.00004 |
| 44.5 | 0.0146 | 0.00067 | 0.00005 | 0.00002 |
| 45 | 0.01357 | 0.00049 | 0.00003 | 0.00001 |
Source: Computed from the game's own shine rule, a Blinn-Phong highlight that sharpens with gloss, halfway between the key light and the eye.
Save picture doesn't blow up the screen. The worker packs the whole page afresh, and the same graphics program runs again with a print switch on, 3200 pixels on the long side, or 2400 on a phone or a device with little memory. At the full table's 512 cells across, that's 6.25 pixels for every cell.
Between cells it samples along curves rather than straight ramps. Where the cells around hold a real step, such as a marker line or a stain's edge, it squeezes the soft ramp back into a crisp edge, and it leaves smooth washes alone. It leans a little toward the ink, so thin lines stay whole, and the paper's fibres ruffle each edge. Pigment settles into the dips of the paper. Crayon wax only catches the tops of the tooth, so paper shows through in specks. Holes, char and the edges of goop are cut a pixel wide.
Then the things lying on the paper are drawn over it from their paintings, without what's in your hand and without the guides. A big drawing is made in bands of rows, each read back with a pause, so the game stays responsive while it saves.
This detail is rebuilt, not simulated. The grid underneath is the same one, and the fine fibre in a print is worked out from position alone, so every print has the same grain.
A small page of blue ink: a stain with a hard edge, a soft wash, a marker line and pencil hatching. Shown both ways, the same patch is drawn twice: on the left as on screen, on the right by the saved picture's rules. Draw marker lines with your finger, or press Draw a marker line. What to look for: the stain's edge goes from a ramp about ten pixels wide to about three, while the soft wash keeps its gradient. Grain appears in the paper and in the pigment. Zoom in to see that the print's edges stay crisp. (Lit flat, without shadows, to keep it quick.)


Everything lying on the paper as an object is a painting: a cup, a toothpick, a bottle, the cat. Things on the table are painted from straight above, as a map shows them, in one gouache style with warm light from the upper left, the same side as the lamp in the graphics program. Tools in your hand are painted from the side, because that's how you see them held.
Each painting starts as a generated image, made with an image model to one shared style, with the game's own art as its guide and the tool's shelf icon beside it, so the thing in your hand is the thing on the shelf. Each one is picked by eye. Scripts then clean it, cut it into sprite sheets and measure things such as where a nozzle points from the paint itself. Parts that take a colour become a layer of their own, so one crayon painting serves every crayon colour.
A thing changes paintings as it changes state. In the released game that means squeezed bottles, a toothpick standing, broken and in pieces, clips open and shut, and each creature's poses. The next update adds more, such as bottles lying on their side, and balls whose panels come from the real shape of a football next update.
Two rules keep it so. Something whose painting hasn't arrived draws nothing until it has, and a tool whose art isn't finished stays off the shelf. And a test reads all the drawing code on the screen side: any function that draws shapes or text must be on a list, with the reason it isn't an object. The next update adds the functions that write pixels next update. Liquids, fire, shadows, light, cables, guides and the buttons' glyphs stay code by design.
Creatures are paintings that bend. A cat's body is one top-down painting stretched over a mesh that follows its bones, so it turns and stretches without a seam. Its legs and tail are painted pieces of their own, and a new pose fades in from another painting.

Professor Oops has animals: flies, ants, a pigeon, a cat, a dog and snails. The rule is that none of them is ever hurt. They dodge, flee or tuck in. A test puts each one through a long list of trouble, from a hammer and a rolling pin to a fire lit beside it, the oven and a long wait. It checks that nothing lands on the animal, no flame is lit under it, it doesn't vanish, and it moved when something came at it.
At release the list held 61 kinds of trouble for 8 animal states, 488 runs in all; about 25 of those kinds use tools still being finished. The next update has 97 kinds for 10 states, 970 runs next update.
Safety comes from the world giving way, not from quick animals. Every press, whatever the tool, goes through one shared rule that reads what is pressing where. A small creature is slid clear by the press itself. In the next update a heavy thing over a cat or a dog waits in the air until the animal has moved, and is taken away if it doesn't next update.
The game holds no advertising code and no analytics library from another company. In one study of 135 apps used by young children, 95 % had advertising Meyer 2019. On Android, the advertising-ID permission that a library could slip in is removed, along with storage permissions, and a test holds the list. On iOS the app declares no tracking. The released game never uses the microphone or the camera. Anonymous counts, with no identifier and no time finer than a day, can be switched off by a grown-up, and start off in the UK and most of Europe.
The whole game is inside the app, the WebAssembly kernels too, packed into the code so nothing is fetched. At release the painter's voice is in the app as well. In the next update, voice and most music become packs fetched when there's a connection, and everything works without them next update. The browser version needs a connection to load.
On the first day, with only a prototype running, several hundred ideas were written down and scored for fun, ease, how fresh they were and how much "you are never allowed to do that" thrill they gave. Three of the eight highest new ideas were a giant's footstep, a giant sneeze and a black hole. The same day a hard rule overrode the scores: only real things a child could really do to paper. No monsters, no giants, no black holes. No test can check that. It's held by whoever decides what gets built. Some gentle ideas that scored low arrived anyway: red cabbage that changes colour and a tea-stained wash as tools, and a sun print and a pencil rubbing with no tool of their own, because the shared physics made them.
Buying, the grown-ups' area and extra play time sit behind a sum such as 37 + 40. It's meant to stop a young child, and the code says so: it's a sum, not a lock. Offers are rare: at most three asks, a week apart, never again after "No thanks, don't ask again". A parent can set a daily limit of 15, 30, 45 or 60 minutes, off by default, and the painter says so two minutes before the end.
a test
Every animal state meets every listed kind of trouble: 488 runs at release, 970 in the next update next update.
Checked by a test on every run
a test
No advertising code and no analytics library from another company. The advertising-ID and storage permissions are removed from the Android build.
Pinned by a test
how it's built
The whole game, the WebAssembly kernels too, is packed into the app, so nothing is fetched to play.
The kernels travel inside the game's code
code
Buying, the grown-ups' area and extra time sit behind a sum like 37 + 40. It's meant to stop a young child, not to be a lock.
Written into the code, and called a sum there
people
No monsters, no giants, no black holes. No test can check that; it's held by whoever decides what gets built.
a decision made on the first day
Each of these runs from something a child does, through a layer many systems share, to what follows. A test pins each one.
Shared: a fingerprint of the copied source
The test run fails, naming the function, until the WebAssembly copy is ported. Pinned by a test.
Shared: dent in the ground height
The grey skips the pressed line, which stays clean, with dark edges where the groove's walls catch the grey. Pinned by a test.
Shared: one press, read by the shared danger rule
The ant is slid clear and never left under it. Pinned by a test.
Shared: two layers folded into one texel by solving the shader backwards
The ketchup hardly pales, and no hard line shows at the oil's front. Pinned by a test.
Shared: a fresh full pack, the same shader with print on
The hole and the table under it are in the saved picture too; a browser check makes sure a real 3200-pixel JPEG comes out in worker and in-thread mode alike.