The Tests-area ratchet in Crm CI
Audit finding, 2026-09-17.
What was missing
The mesh gate prints one line per NodeType and both shapes begin with ok:
ok Crm/Board: compile=Ok render=ok tests=ok
ok Crm/Question: compile=Ok render=ok tests=skipped
The second means the type declares no executable Tests area, so the gate compiled it,
rendered it, and asserted nothing about its behaviour — in a word nobody had to act on.
Every sibling repo has ratcheted that word for weeks: MeshWeaver.Plugins, MeshWeaver.Reinsurance,
MeshWeaver.Manufacturing and MeshWeaver.Education each run scripts/check-test-suites.py over the
gate log and fail the PR on a new tests=skipped. This repo had the allow file and nothing
else. plugin-tests.allow was created empty on 2026-08-28; ci.yml never mentioned
check-test-suites.py; no job read it. A ratchet with no script and no job is indistinguishable
from one that passes, which is precisely the failure mode the ratchet exists to remove.
What it enforces now
tests-ratchet — Tests-area ratchet over the gate log — is a thin CONSUMER of the shared gate,
not a second copy of it. node-repo-gate.yml uploads the tester's stdout as gate-log-<sha> and
names it in its gate-log-artifact output; this job downloads that and reads it:
- a type listed in
plugin-tests.allowmay betests=skipped— reported as debt, does not fail; - a type NOT listed that is
tests=skippedis a NEW hole — fails; - a listed type that now RUNS its
Testsarea is STALE — fails until the line goes; - the list may only SHRINK:
--base-refdiffs it against the PR's MERGE BASE and fails on an addition, closing the trapdoor where a PR adds a type with no suite and excuses it in the same diff; - a type whose
compile=orrender=FAILED isblocked, never counted as a hole — the gate stopped before reaching its Tests area, and the compile error is the actionable thing; - a
tests=okwhose verdict line carries NON/M passedcount — fails. The gate's probe reads the rendered summary for the first such token and, finding none, passes the type anyway with the detailall rendered cases green: a verdict that cannot tell a suite of thirty executed cases from one that silently shrank to a single case. Ten suites across the family were in that state on 2026-09-17 (MeshWeaver.PluginsHosting/TestsAreaPassCountToken.md); none of them was here, and this keeps it that way.
It is wired like a gate: gates-executed watches it (a skipped ratchet is a hole), and
tag-modules and publish-bake wait for it. scripts/test-released-platform-ci.py names it in
the watched roster, so the skip detector cannot quietly stop following it.
Why the allow file stays EMPTY — measured
Main run 35197784164 (2026-09-17, gate shard 1/1, commit 55bd9bc9) gated all 14 Crm/*
NodeTypes and every one reported tests=ok with a real case count:
[PASS] Crm (133 node(s), 14 type(s))
ok Crm/Board: compile=Ok render=ok tests=ok
47/47 passed
ok Crm/Client: compile=Ok render=ok tests=ok
33/33 passed
…
There is no debt to excuse, so seeding the file would only make future debt permanent. Empty is
the ratchet's strongest state: ANY tests=skipped from now on is a new hole and fails the PR.
The same run settles the --owns question. This repo seeds the upstream (upstream-seed: plugins)
and the tester marks every seeded package in its own summary — all sixteen print
[upstream: installed, not gated here] with 0 type(s), and only Crm carries types. So no
upstream line can reach the ratchet, the filter stays OFF, and an upstream type appearing here at
all would be a REGRESSION in the seeding that should redden this job rather than be filtered out of
sight.
Reading a red
Crm/X reported 'tests=skipped'— writeCrm/X/Test/*.csand expose aTestslayout area on the type. Do NOT add a line toplugin-tests.allow; the growth check refuses it anyway.Stale plugin-tests.allow entry— the type gained a suite. Delete its line.the gate-log artifact is present but gate.log is missing or emptyand the other absent-evidence errors — the ratchet refuses to pass on evidence it cannot read. Fix the gate, never the reader.
Full evidence for the sibling half of this audit — ten suites whose tests=ok verdict carried no
case count — is in MeshWeaver.Plugins, Hosting/TestsAreaPassCountToken.md.