[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
3.8 KiB
3.8 KiB
ktg-plugin-marketplace (catalog)
Catalog repository for the ktg-plugin-marketplace. After the polyrepo migration this repo hosts only
the marketplace manifest and the catalog-level docs; every plugin and the shared design-system live in
their own Forgejo repositories under https://git.fromaitochitta.com/open/.
What lives here
.claude-plugin/marketplace.json— the marketplace manifest (plugin entries point at external repos)README.md— the landing/catalog pageCONVENTIONS.md— marketplace-wide conventions inherited by every plugin repoGOVERNANCE.md— governance + fork-and-own model.mailmap,.gitleaks.toml,.gitleaksignore— shared git-hygiene baselines
Catalog maintenance
- Marketplace conventions: see CONVENTIONS.md.
- Adding/updating a plugin entry: edit
.claude-plugin/marketplace.json(externalsource: "url"with a pinnedref) and re-state the plugin in README.md with its verified version. - Plugin source, issues, and releases live in each plugin's own repository — not here.
- Releasing a plugin (canonical path —
scripts/release-plugin.mjs): since the polyrepo split, a release is a TWO-repo act — tag the plugin repo AND bump the catalogref. Forgetting the second step strands users on the old version (the exact drift this helper exists to prevent). Runnode scripts/release-plugin.mjs <plugin> [--version X.Y.Z]— dry-run by default; it REFUSES unlessplugin.json== README badge == the target version AND thevX.Y.Ztag exists, then prints the planned bump. Apply with--write [--commit] [--push];--create-tagmints+pushes a missing plugin tag first. On--writeit bumps the catalogrefAND the catalog README's per-plugin`vX.Y.Z`label together (andgit adds both on--commit). Because it only moves both to a verified, tagged, consistent version,check-versions.mjsis green by construction. Never hand-edit arefor a README label for a release — use this. Pure planner + label reconciler covered byscripts/release-plugin.test.mjs. - Version-consistency gate: run
node scripts/check-versions.mjsbefore committing anyrefchange. For each plugin it checks (against the sibling repo) that the catalogrefresolves to a real git tag (ERROR if dangling — breaks install), thatplugin.jsonversion == README version-badge (ERROR), that the catalog README's per-plugin`vX.Y.Z`label == the catalogref(ERROR — the human-facing doc must not misstate the installed version), and that the catalogrefmatchesplugin.jsonversion (WARN — catalog lags or an unreleased bump). Exit 1 on any ERROR;--strictalso fails on WARN. Pure-function core covered byscripts/check-versions.test.mjs(node --test scripts/check-versions.test.mjs). - Stat-badge mirroring (part of the same gate): each plugin block in the catalog README ends in a
stat line (
7 agents · 16 scanners · 21 commands · 1441 tests · [Full documentation →]). The gate compares every number on that line against the plugin's own shields badge for the same axis, and ERRORs when they disagree — the catalog must not overstate a plugin. The rule is per-AXIS, not per-plugin: an axis the plugin does not badge is skipped silently, so there is no exception list to maintain. Measured 2026-08-02: 21 axis-pairs are badge-covered, and 14 axes across 8 of the 11 plugins are badge-less and therefore ungated — those numbers still rot and need a human pass (repo-mailbox's read6 CLI scripts/251 selftest checksagainst a true 8 / 374).N+in the catalog is read as a lower bound, not an equality. Never hand-edit a stat line to silence the gate — the plugin's badge is the source for every stat number; fix the catalog to match it.