fix(catalog): bryt stat-linje-vranglåsen mellom de to pre-flightene

Q3e innførte en pre-flight som leser den NYE ref-ens badger, mens applyRelease'
pre-flight leser den PINNEDE ref-en. De krevde motsatte verdier av samme
stat-linje, og den pinnede ref-en flyttes først av nettopp den skrivingen som
blokkeres — så ingen release som endrer et badget tall kunne fullføres. Målt på
to levende ordrer (repo-mailbox 0.35.0, llm-security 8.0.0).

Verre enn en blokk: --create-tag er med vilje ugatet på den katalog-brede
pre-flighten, så et ekte løp ville MINTET OG PUSHET taggen og deretter blokkert
— en publisert tag mot en katalog som aldri kan bumpes.

Fiks: preflightErrors tar navnet på pluginen som slippes og ser bort fra DENS
stat-funn. Ingenting blir uverifisert — (a) validerer stat-linja mot målet før
noe røres, og post-write-gaten validerer den mot den nå-pinnede nye ref-en. Kun
vinduet der den pinnede ref-en er kjent stale hoppes over.

Vakten er smal i tre ledd: kun den pluginen som slippes, kun funn med
kind='stat' (diskriminator i check-versions.mjs, aldri prosa-match), og en
ERROR uten ERROR-funn blir aldri frikjent. Hengende ref, badge-avvik, feil
README-etikett og død homepage blokkerer som før.

Valgt denne framfor å la applyRelease skrive stat-linja selv, fordi den ville
måttet innføre en maskinpolicy for badge-løse akser — og de er ved dokumentert
org-beslutning et menneskelig skjønn.

Iron Law: 5 nye tester, 2 røde før fiksen. 172/172 grønne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-18 01:05:39 +02:00
commit 5a893e3bfd
3 changed files with 109 additions and 3 deletions

View file

@ -158,6 +158,9 @@ export function statMismatchFindings(catalogStats, statBadges) {
const shown = approx ? `${stated.atLeast}+` : String(stated);
findings.push({
level: 'ERROR',
// `kind` is a machine-readable discriminator, not decoration: release-plugin.mjs's
// pre-flight must tell a stat finding from a dangling ref WITHOUT matching on prose.
kind: 'stat',
msg: `catalog says ${shown} ${axis} but the plugin's badge says ${badge} (catalog stat line is stale)`,
});
}