The 2026-08-02 reading (24 gated / 15 ungated across 7 of 11 plugins) predated repo-standard entering the catalog and repo-mailbox badging its two remaining axes. Re-measured 2026-08-04 at every pinned ref with the gate's own parsers: 42 catalog axis-claims, 27 badge-covered, 15 badge-less across 7 of 12 plugins, source=ref for 12/12. The two readings reconcile exactly (24+3, 15-2+2). Two premisses corrected while measuring: - graceful-handoff has NOT lost its tests/hooks badges. Both badge-removing commits are unreleased (after v3.1.0), so at the pinned ref the catalog's "30 tests" is gated. Recorded at pickStatSource as the opposite failure direction to the llm-security case: reading the worktree misreports COVERAGE, not just values, and neither example alone would have caught it. - the "251 selftest checks" correction is not settled: CLAUDE.md said 370, check-versions.mjs said 374, and repo-mailbox's own README at v0.19.0 implies 390. Moot for the gate (badged and green at v0.20.2) and not re-measured, so the disagreement is flagged rather than laundered into one number. Badge-less VALUES were not re-audited this session and do not need to be: only two refs have moved since their audit, so all 15 stand measured at the ref they are pinned to. Re-measurement is triggered by a ref moving, not by the calendar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PtnSwCLpUR3Hk8SHkPoxX4
76 lines
6.2 KiB
Markdown
76 lines
6.2 KiB
Markdown
# 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. Since no ungated plugin's ref has moved
|
||
since its audit, every ungated value currently stands measured at the ref it is pinned to.
|
||
**⚠️ The `251 selftest checks` correction is itself unresolved and must not be cited as settled:**
|
||
three records disagree on the true value at v0.19.0 — this file said 370, `check-versions.mjs`
|
||
said 374, and repo-mailbox's own README at that tag implies 390 (`183 + 134 + 73`). It is moot for
|
||
the gate (repo-mailbox badges the axis now, 398 at v0.20.2, green) and was **not** re-measured
|
||
2026-08-04. It stands as the standing 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.**
|