Commit graph

4 commits

Author SHA1 Message Date
780f86ec9f 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
2026-08-02 21:26:27 +02:00
fc95cbd300 feat(check-versions): gate the catalog's stat lines against plugin badges [skip-docs]
[skip-docs]: the user-facing doc here is CLAUDE.md, not README.md. This is a
maintainer-side consistency gate — the catalog landing page should not describe
it — and CLAUDE.md gains a full paragraph covering the rule, the measured
badge-less gap, and the never-hand-edit-a-stat-line instruction. README.md
changes by exactly one number because the gate found it wrong.

The catalog restates each plugin's counts in a per-plugin stat line, and those
numbers rot silently: nothing compared them to anything. Measured across all 11
plugin READMEs today, config-audit's line claimed 1410 tests while the plugin's
own badge said 1441.

Rule is PER-AXIS, not per-plugin. For each number on a catalog stat line, if the
plugin carries a shields badge for that axis, they must agree (ERROR otherwise);
if it carries no such badge, the axis is skipped. This was measured, not assumed:
21 axis-pairs are badge-covered, but 14 axes across 8 of the 11 plugins are
badge-less (voyage 4, ms-ai-architect 3, repo-mailbox 2, ai-psychosis 2,
linkedin-studio 1, claude-design 1, graceful-handoff 1). A per-plugin exception
list — the original sketch, scoped around voyage alone — would have had to name 8
of 11 repos and be hand-edited for every new axis.

Stated plainly rather than hidden: those 14 axes stay ungated. repo-mailbox's two
were 6 and 251 against a true 8 and 374 (fixed in e9054f8).

Parsing is measured against the real corpus: shields' `--` literal-hyphen escape,
`_`/`%20` spaces, zero as a real count, non-numeric badges (version/platform/
license) excluded, parenthetical asides read as their own axis ("5 skills (389
docs)"), doc/docs/references/reference_docs/knowledge_docs folded onto one axis,
and `N+` read as a lower bound.

Only the catalog's config-audit number changed; the plugin badge is the source.
Tests 106 -> 117 (+11). 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
2026-08-02 21:12:50 +02:00
2e1d206ab3 feat(catalog): gate catalog README labels against ref + close the drift
The catalog README's per-plugin `vX.Y.Z` labels were an UNGUARDED surface:
check-versions validated each plugin's OWN README badge, never the catalog
README's labels, so they drifted (config-audit shown v5.5.0 while pinned to
v5.7.0; voyage v5.1.1 while pinned to v5.6.0) — the doc misstated what
`claude plugin install` actually resolves.

Close the class, same pattern as the ref surface:
- check-versions.mjs: new ERROR rule "catalog README label == catalog ref"
  via pure extractCatalogLabel() (matches the /open/<name>) heading, takes the
  first `vX.Y.Z`, ignores a trailing lang/flag badge). No legitimate transient
  state lets label != ref, so ERROR (not WARN). +5 tests.
- release-plugin.mjs: on --write, bump the README label atomically with the ref
  via pure reconcileReadmeLabel() and git add README.md on --commit, so future
  releases keep label and ref in lock-step. +4 tests.
- README.md: reconcile the 2 stale labels (config-audit -> v5.7.0,
  voyage -> v5.6.0). Gate now 9 OK / 1 WARN / 0 ERROR.
- CLAUDE.md: doctrine updated to document the new gate rule + atomic label bump.

ms-ai-architect stays WARN by decision (1.16.0 is unreleased WIP, never tagged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cm2RxKbomdLqjiWGcwCCPi
2026-06-22 13:38:23 +02:00
a8d44e6d3f feat(scripts): add marketplace version-consistency gate
scripts/check-versions.mjs cross-checks every plugin in marketplace.json against
its sibling repo:
- catalog ref must resolve to a real git tag    → ERROR (dangling = install breaks)
- plugin.json version == README version-badge    → ERROR (internal corruption)
- catalog ref == plugin.json version             → WARN (catalog lags / unreleased bump)
- sibling repo missing                           → SKIP

Exit 1 on any ERROR; --strict also fails on WARN. Pure classifier covered by
check-versions.test.mjs (9 tests, node --test). Documented in CLAUDE.md
catalog-maintenance. Run before committing any ref change.

Current run: 8 OK, 2 WARN (linkedin-studio, ms-ai-architect — catalog ref lags an
untagged plugin.json bump), 0 ERROR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ter3E2JSi1Khgmuf2kady8
2026-06-19 23:19:22 +02:00