DOCUMENTATION / PART 3 — INTERFACES3.4

3.4 The gate suite

Fifty-eight tools/check-*.sh scripts, sixty-one module selftests and one window selftest. They are not tests of the toolkit's results in the wild — no gate can tell you whether the tower you are looking at is the one you think — they are tests of the claims that would otherwise be quietly false: that every verb is reachable, that every decoder agrees with a referee, that the document you are reading describes the thing that exists.

Four kinds, and they fail differently.

Structural gates: does the interface still hold together

Gate What it asserts The drift it prevents
tools/check-paths.sh every path the tree assumes resolves: a directory a module writes into is created, a script a table names exists a write into a directory nobody made, a card pointing at a deleted script
tools/check-verbs.sh every documented verb sits in one of its submenu groups, or is a known modifier, or is exempt plumbing a feature nobody can click
tools/check-gui-text.sh no string literal beginning with -- is handed to an API that renders text a button labelled --tr069-audit, a verb moved onto the screen instead of a sentence
tools/check-gui-pages.sh 22 checks that the spec-driven pages keep a card's answer inside the card — no near-black OUTPUT scroller bolted to the bottom, which made every module look like a terminal the log well creeping back into a page
tools/check-glossary.sh every key printed has a plain-words row; no row is dead; no label contains a verb token; every Workflows step names a verb its module documents vocabulary invented at the call site, and a route pointing at nothing
tools/check-theme.sh every theme sheet is named in the manifest, balanced, regenerable, and the manifest itself is current the silent "Ember does nothing" bug
tools/check-tui.sh the terminal workspace compiles, its keys are 01..N in table order and unique, it refuses a non-TTY, and it renders in a real pseudo-terminal duplicate menu keys, and a workspace that draws nothing
tools/gen-module-index.sh --check module_index.tsv and native/src/module_index.c match the module table an index that describes a previous version of the tree
tools/gen-theme.py --check the Ember sheet is exactly what today's base sheet generates a theme edited by hand and then left behind

Two of these deserve their reason written down, because both are gates that exist because of a bug rather than a plan.

check-verbs.sh insists that every non-modifier verb is placed in a submenu. Its modifier list used to live inside the gate as one 237-name alternation; it is now tools/verb-modifiers.txt, read by both the gate and the terminal workspace, so the two cannot disagree about what counts as an action. The list is explicit rather than a wildcard on purpose: a rule like "anything matching --.*-.* is a modifier" would silently stop requiring a control for a real verb.

check-tui.sh asserts that the menu keys are 01..61 with no duplicates, because the launcher's fn_for_key() returns the first match — a duplicate key does not fail loudly, it makes a module unreachable.

Codec oracle gates: does the decoder agree with somebody else

The largest group, and the reason to trust a decoded field. Each one feeds a decoder in the tree and a referee outside it the same bytes, then compares.

The referees are named in each gate's header, and they are of four kinds: tshark (a dissection of the same bytes), pycrate (an independent Python implementation of the specification), published test vectors (3GPP's own, or the values a specification prints), and a sibling module that implements the same thing by a different route — which is the weakest of the four and is labelled as such.

Domain Gates
GSM check-gsm-si (tshark and pycrate, with five negative controls), check-auth-oracle, check-keystream
UMTS check-umts-rrc, check-umts-sib, check-umts-bch, check-umts-phy, check-umts-sccpch, check-umts-uplink, check-umts-catcher, check-umts-catcher-pcap
LTE check-lte-sib-codec, check-lte-nb-codec, check-lte-phy-oracle, check-lte-rm-oracle, check-lte-corpus, check-lpp-codec
5G / NR check-nas-vectors, check-nas-identity, check-suci-catcher, check-nr-phy-oracle, check-ngap-codec, check-xnap-codec
Core network check-gtp-codec, check-pfcp-codec, check-diameter-codec, check-sba-codec, check-sip-codec, check-vowifi-codec
SS7 / RAN check-ss7-codec, check-ss7-map, check-sgsap, check-ranap-codec, check-rua-codec, check-x2ap-codec, check-supl, check-scp03t, check-li-ber
SIM / device check-sim-codec, check-apdu-codec, check-stk-codec, check-ota-codec, check-ota-packet, check-ota-response, check-ussd-codec, check-smpp
Physical layer check-phy-seqs, check-media-leg, check-calls
Structure of the tree check-paths, check-verbs, check-gui-text, check-gui-pages, check-glossary, check-theme, check-tui
Experiments check-evil-twin-lab, check-ransacked-corpus

A codec gate is only worth its runtime if it can fail. check-gsm-si carries five negative controls: it copies the module, breaks its System Information builders one at a time in five specific ways — drop the L2 pseudo-length, add a LAPDm header to a BCCH block, put the LAI before the cell identity, put the cell identity into SI4, count ARFCNs from the wrong end — and asserts that each broken build produces the expected change. Without that, a gate that passes might be a gate that compares two identical wrong things.

The SI framing fix in 1.0.78 is the worked example of the whole idea: the toolkit's own builder and its own decoder disagreed about where the cell identity goes, two independent referees sided with the decoder, and the gate that now covers it was written in the same pass as the fix, with the disagreement as one of its controls.

Module selftests: does this module's own arithmetic hold

Every module has --selftest, and it is the same idea one level down: fixture input, printed expectation, exit non-zero on a mismatch. They are what you run after a merge, on a machine with no radio, in under a minute each:

for m in modules/*.sh; do bash "$m" --selftest >/dev/null || echo "FAIL $m"; done

07_gsm_attack --selftest is 357 assertion rows covering the catcher sequence, the length indicators, the message types, the ciphers and the observation store. 00_deps --selftest injects a stub tool directory to prove that detection is by use rather than by file. 58_suci_catcher --selftest proves the record format its live feed reads.

The window's selftest, and the gates that are not shell

imsisting-gui --selftest runs without a display and checks what a screenshot cannot: the map's pan arithmetic and its zoom floor, the fleet page's column lookup, the posture chips' reading rules (an algorithm the toolkit cannot place never comes out strong; the newest row wins), and that both appearance settings are deliverable — which is the row that caught the unpackaged theme.

Running them all

There is no single runner on purpose; each gate is a sentence you can read and a decision you can make. The order that catches the most in the fewest minutes:

tools/check-paths.sh            # nothing points at nothing
tools/gen-module-index.sh --check
tools/check-verbs.sh            # slow: it reads every module
tools/check-gui-pages.sh
tools/check-gui-text.sh
tools/check-glossary.sh
tools/check-theme.sh
tools/check-tui.sh
native/builddir/imsisting-gui --selftest

then the codec group for whichever protocol you touched.

A gate's number is not the point and neither is a green board. The point is the sentence each one asserts; when a gate fails, the useful move is to read its header comment, which states what it holds and — just as honestly — what it cannot see.


Part 3 has described the surfaces: the command line that is the truth, the terminal that indexes it, the window that draws it, and the gates that keep the drawing honest. Part 4 is the catalogue itself — the sixty-one modules, one page each, in the order the drawer lists them — followed by this window's ten pages described one at a time, so that "a page each" means the same thing for a module as it does for the interface that shows it.