fix(check-versions): mirror stats against the pinned ref, not the working tree [skip-docs]

Found live minutes after shipping fc95cbd: llm-security went ERROR on scanners
(23 vs 22) and tests (2013 vs 2034). The catalog was RIGHT and the gate was
wrong. llm-security had committed past its v7.8.3 tag without bumping the
version, and the gate was reading the sibling working tree — but the catalog
documents what INSTALLS, and `ref: v7.8.3` still installs 23/2013.

Stat badges are now read with `git show <ref>:README.md`, falling back to the
working tree only when the ref cannot be read (a ref resolving to nothing is
already its own ERROR, so the fallback cannot hide a dangling ref). The
version-badge check is unchanged and still reads the working tree: that one is
about the plugin's internal consistency, not about what the catalog promises.

This also corrects a stat I got wrong in fc95cbd. I had moved config-audit from
1410 to 1441 tests off the working tree; at the pinned v5.13.0 the badge says
1398. 1441 is unreleased. The catalog now says 1398 — what installs.

[skip-docs]: CLAUDE.md carries the rule and the "check `git show <ref>:README.md`
before believing the working tree" instruction; README.md changes by one number
because the gate was wrong about it.

Tests 117 -> 120 (+3, all regression). Gate green at 11 OK / 0 WARN / 0 ERROR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDSiMcgLMpEETwtkc86Nym
This commit is contained in:
Kjell Tore Guttormsen 2026-08-02 21:26:27 +02:00
commit 780f86ec9f
4 changed files with 63 additions and 6 deletions

View file

@ -9,6 +9,7 @@ import {
extractCatalogLabel,
classifyPlugin,
extractStatBadges,
pickStatSource,
extractCatalogStats,
} from './check-versions.mjs';
@ -269,3 +270,25 @@ test('stat maps omitted (legacy callers) → mirroring skipped entirely', () =>
});
assert.equal(r.status, 'OK');
});
// Regression, found live 2026-08-02: llm-security had committed past its v7.8.3 tag
// (scanners 23->22, tests 2013->2034) WITHOUT bumping the version. The gate read the
// sibling's working tree and reported the catalog stale — but the catalog documents
// what INSTALLS, and `ref: v7.8.3` still installs 23/2013. The catalog was right and
// the gate was wrong. Stat badges must therefore be read at the pinned ref.
test('pickStatSource prefers the README at the pinned ref over the working tree', () => {
const atRef = 'https://img.shields.io/badge/scanners-23-cyan';
const atWorktree = 'https://img.shields.io/badge/scanners-22-cyan';
assert.equal(pickStatSource({ atRef, atWorktree }), atRef);
assert.equal(extractStatBadges(pickStatSource({ atRef, atWorktree })).get('scanner'), 23);
});
test('pickStatSource falls back to the working tree only when the ref cannot be read', () => {
const atWorktree = 'https://img.shields.io/badge/scanners-22-cyan';
assert.equal(pickStatSource({ atRef: null, atWorktree }), atWorktree);
assert.equal(pickStatSource({ atRef: null, atWorktree: null }), null);
});
test('an empty README at the ref is a real read, not a failed one', () => {
assert.equal(pickStatSource({ atRef: '', atWorktree: 'badge/scanners-22-cyan' }), '');
});