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-ratchetTests-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:

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

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.

Reconnecting…
The server was updated. Reloading the page to pick up the latest version.