Quality and checks#
Quality here is measured on numbers rather than judged by eye, because the character creator breaks in ways a single screenshot cannot show: an element shifts by 0.1 of a unit and pokes through an arm in one animation but not in another.
Gates and checks#
All of these run on the same code that goes to production — not on a mock-up.
| Tool | What it checks |
|---|---|
check_props_parity.py | parity of the tables: identical blocks, zones, colours and palettes in the website version (JavaScript) and in the app (Kotlin). Any drift would mean a different look on the phone and on the web |
run_anim_audit.py | pushes the character through every animation clip and measures real intersections of blocks in 12 outfit sets |
check_gaps.py | the opposite of the collision audit: no accessory may float — every block has to touch the body or the item it is attached to |
film_strip.py | returns a strip of frames from an animation, for judging movement rather than a single pose |
dump_atlas.py | dumps the character atlas to a PNG, so the painting can be looked at without guessing what is where |
run-checks.sh | all of the above as one command, with its own test environment |
android-compile-guard.py | a static audit of the Android code before a release: missing imports, name clashes, calls to suspending functions from places that must not wait. It catches classes of errors that would otherwise cost a full APK build round |
glsl-check.py | compiles the map layer shaders in a real WebGL2 context and checks that every parameter is used — this is how a bug that switched off all figures on the map was found |
tools/perf/run.sh | map performance: cost per frame, number of draw calls, behaviour from one pawn → plus finds → plus a route → plus players → plus a lobby → plus bots |
| marker and bot tests | parity of markers and bots between the website and the app (the same sizes, thresholds and colours on both sides) |
shoot_legend.py | documentation screenshots taken from the real code, checking for each marker whether it is in frame, whether the layer drew it and whether it is actually visible in the image |
The checks are arranged in layers, so a broken change is caught as early as possible:
- Before pushing code — a quick pass of about ten seconds that stops the push when the character code is inconsistent. Because the APK is built from tags of this same repository, a bad commit cannot become a bad release unnoticed.
- Once a week — the full collision and gap audit runs automatically and the result goes to Telegram. If work in progress is in the tree, the run is deliberately skipped so it does not report false alarms.
- Repository-level checks on our own server — the structural checks of the repository are our own script, not a hosted pipeline: GitHub holds the repository, the tags and the history (see APK releases).
- On production, without a phone — after a deployment, verification runs against the live API: that the pages exist in the brain graph, that screenshots load in the panel, and that new rules behave in the real service rather than only in a test.
How to run the checks#
Everything is a command in the repository, so a result can be reproduced by anyone:
bash tools/lab/run-checks.sh --quick # syntax + parity + self-tests, about 10 s
bash tools/lab/run-checks.sh # also the animation audit (12 sets), about 6 min
python3 tools/ci/check-user-docs.py # the documentation gate (structure, links, assets)
python3 tools/ci/check-user-docs.py --self-test # proof that the gate can go red
bash scripts/deploy-docs.sh --check # report drift between repository and server, changes nothing
The full animation audit needs a local lab server and a directory with the drawing scripts; the quick pass does not, which is why the pre-push hook uses the quick one. The long run is the weekly one.
What the documentation gate watches#
The gate does not judge writing style. It enforces structure, so that “the documentation is up to date” can be checked by a machine instead of promised:
| # | Rule |
|---|---|
| 1 | every entry in the feature list has a page in both languages, and its anchor exists in both |
| 2 | every image referenced by the list or by a page really exists on disk |
| 3 | every internal link points to a page and an anchor that exist |
| 4 | no orphan pages: every page is listed in the site tree |
| 5 | every option from the app's settings catalogue has a description — the only rule that forces content to be current, not merely consistent |
| 6 | the Polish and English site trees have the same pages |
| 7 | a scan for secrets and server addresses in published content — it blocks |
| 8 | every page has a version footer and no leftover placeholders |
| 9 | in release mode: the version in the feature list matches the version in the Android build file |
| 10 | the documentation stylesheet has no trap that would silently cut a rule |
--self-test deliberately breaks things and requires that each mutation turns the gate red — a gate that has never failed proves nothing.
Verification on a device#
Some things can be verified without a phone; a few cannot, and it is honest to say which is which.
| What | How |
|---|---|
| Map logic and markers | pure Kotlin: 95 of 95 checks — sizes, zoom thresholds, marker hits, bot labels |
| Map performance | the harness reports OK with 72 tests; three bots cost +1 draw call per frame, and marker layers add 0 style sources and 0 style layers |
| Markers on the website | 224 of 224 — sprites, palette, thresholds and state order match the app |
| Android code before release | clean: no missing imports, no blocking calls; 8 shader programs compile and link in WebGL2 |
| Map legend screenshots | all good: every marker visible in the image, zero circles drawn on the map |
| Character audit | gaps OK — 83 blocks in 60 sets, nothing floating; the largest in-motion intersection was 0.085 of a unit inside the silhouette and therefore invisible |
What a desktop verification cannot replace:
- the AR view — it needs Google Play Services for AR, so it does not start in an emulator; those frames are judged on a real phone, by the owner;
- visual taste — the animation strip and renders are for the eye; the numbers only say whether anything intersects;
- the true look on a specific device — screen size, brightness and performance are the phone's, so a measurement is always paired with a real-device check before a release is called done.
Documented for app version 0.120.1 (updated 2026-09-26).
Machine translation — the Polish version prevails.