ktg-plugin-marketplace/CLAUDE.md
Kjell Tore Guttormsen 7e7e060b67 docs(catalog): verify the ungated-values claim on the catalog side too
"No ungated ref has moved since its audit" only proves the badge source is
unchanged. Catalog prose is itself ungated, so an ungated stat value could have
been restated by any commit with nothing catching it — which would have made
the no-re-measurement justification false.

Checked by diffing extractCatalogStats against README.md at db1e80b (08-02):
the only ungated numbers the catalog has restated since are repo-standard's two,
absent then and measured 08-04. The claim holds; it is now stated as a two-sided
verification rather than a one-sided inference.

Sharpens the 251-selftest-checks flag with what that diff also showed: the
catalog's own 08-02 stat line already said 370, so two independent records agree
on 370 and check-versions.mjs's 374 reads as a transcription slip.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtnSwCLpUR3Hk8SHkPoxX4
2026-08-04 21:46:38 +02:00

79 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 page
- `CONVENTIONS.md` — marketplace-wide conventions inherited by every plugin repo
- `GOVERNANCE.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` (external `source: "url"` with
a pinned `ref`) 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 catalog `ref`. Forgetting the second
step strands users on the old version (the exact drift this helper exists to prevent). Run
`node scripts/release-plugin.mjs <plugin> [--version X.Y.Z]` — dry-run by default; it REFUSES unless
`plugin.json` == README badge == the target version AND the `vX.Y.Z` tag exists, then prints the
planned bump. Apply with `--write [--commit] [--push]`; `--create-tag` mints+pushes a missing plugin
tag first. On `--write` it bumps the catalog `ref` AND the catalog README's per-plugin `` `vX.Y.Z` ``
label together (and `git add`s both on `--commit`). Because it only moves both to a verified, tagged,
consistent version, `check-versions.mjs` is green by construction. Never hand-edit a `ref` or a
README label for a release — use this. Pure planner + label reconciler covered by
`scripts/release-plugin.test.mjs`.
- **Version-consistency gate:** run `node scripts/check-versions.mjs` before committing any `ref`
change. For each plugin it checks (against the sibling repo) that the catalog `ref` resolves to a
real git tag (ERROR if dangling — breaks install), that `plugin.json` version == README
version-badge (ERROR), that the catalog README's per-plugin `` `vX.Y.Z` `` label == the catalog
`ref` (ERROR — the human-facing doc must not misstate the installed version), and that the catalog
`ref` matches `plugin.json` version (WARN — catalog lags or an unreleased bump). Exit 1 on any
ERROR; `--strict` also fails on WARN. Pure-function core covered by
`scripts/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 · 1398 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. **Re-measured 2026-08-04 at the pinned refs, all 12 plugins: 42 catalog axis-claims —
27 badge-covered · 15 badge-less across 7 of the 12 plugins** and therefore ungated. That supersedes
the 2026-08-02 reading (`24 · 15 across 7 of 11`); only two entries moved in between and both
reconcile exactly — repo-mailbox now badges the two axes it did not (`+2` gated, `-2` ungated) and
repo-standard entered the catalog (`+1` gated, `+2` ungated). The 15 ungated axes were hand-audited
at their pinned tags — 13 on 2026-08-02 (**14 of that pass's 15 were exact**; the defects were
repo-mailbox `6 CLI scripts` (true 8) / `251 selftest checks`, and voyage `500+ tests` against a
measured 832), and repo-standard's two on 2026-08-04. Every ungated value currently stands measured
at the ref it is pinned to — verified on **both** sides 2026-08-04, because a ref that has not moved
only proves the *badge source* is unchanged and catalog prose is itself ungated: no ungated plugin's
ref has moved since its audit, **and** diffing `extractCatalogStats` against the 08-02 README shows
the only ungated numbers the catalog has restated since are repo-standard's two (absent then).
**⚠️ The `251 selftest checks` correction is not fully settled**, though the weight is on 370: this
file *and* the catalog's own 08-02 stat line both record the axis as corrected to 370,
`check-versions.mjs` said 374 (most likely a transcription slip), and repo-mailbox's README at
v0.19.0 implies 390 (`183 + 134 + 73`) — its own prose being ungated too. Moot for the gate (they
badge the axis now, 398 at v0.20.2, green) and **not** re-measured. It stands as the proof of the
cost: an ungated number rots, and so does the record of having fixed it.
`N+` in the catalog is read as a lower bound, not an equality, so `500+` was never gate-visible —
ungated axes rot in silence and need a re-run of this pass **whenever a ref moves**. **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.
- **Counting rules for a badge-less axis (calibrated against the badged plugins, 2026-08-02).** When
the catalog must count an axis itself, count it the way the badges do, or the numbers stop being
comparable across plugin blocks: **hooks = hook COMMAND entries** in `hooks/hooks.json` (not
events, not matchers — the three diverge, and `commands` is what matched the badge on all 6 badged
plugins), and **tests = ` tests` from `node --test`**, not ` pass` (config-audit's badge 1398 is
its `tests` count; `pass` was 1375). Measure in an extraction of the tag
(`git archive <ref> | tar -x -C <tmp>`), never the sibling working tree.
- **The stat mirror reads the plugin README AT THE PINNED `ref`, never the sibling working tree.**
The catalog documents what *installs*, and that is the tag. A plugin that commits past its tag
without bumping its version — measured 2026-08-02 on both llm-security (scanners 23→22, tests
2013→2034) and config-audit (tests 1398→1441) — would otherwise make the gate demand that the
catalog restate unreleased numbers, which is exactly backwards. **When the gate flags a stat,
check `git show <ref>:README.md` in the plugin repo before believing the working tree.**