The 0.1.0 entry says "Eleven checks" and then lists twelve. classifyRepo spreads exactly twelve check* calls, and the README table has twelve rows. Found when catalog measured the tag independently and reported twelve against a "fourteen" this repo had put in a coord message -- a number that was never measured here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EeNsGsWukggfmLQ926WZPx
6.5 KiB
6.5 KiB
Changelog
All notable changes to this project are documented here. Format follows Keep a Changelog; versioning is Semantic Versioning.
0.1.0 — 2026-07-27
First release. Covers the checks that a single repository can answer on its own.
Added
- The gate (
scripts/repo-standard-check.mjs) — pure classifiers with all I/O resolved into their input, findings taggedERROR/WARN/SKIP/OK, exit 1 onERROR. Twelve checks: README first screen, install block, install truth, required headings, files required by the repo's class and traits,open/<name>references, relative links, licence claim, badges, boilerplate, version consistency and description length. - Taxonomy register (
register/repos.json) — one central file mapping each repository to its class, plus the per-class file and install requirements.--refreshcompares it against the live org listing. - Three-outcome reference check — "matches no repository" (
ERROR) is a separate finding from "matches something that is deliberately not a repository" (WARN). Sharing an outcome would let real dead links hide among correct text. Only names in URL position are treated as references; the.gitsuffix is normalised first. - Two-axis findings — every
ERROR/WARNcarries a bucket alongside its level:broken(a stranger is blocked or misled),missing(an expected artefact is absent),weakening(present, but it reads as amateur). Output is grouped by bucket, because that is the order findings get acted on. - Traits, a second axis beside class — class is structural and readable off
the catalog; a trait is about what the code does.
securityattaches aSECURITY.mdrequirement and a## Known limitationssection. - Required README headings per class —
## Install,## Non-goals,## Changelog. A heading present at the wrong depth is its own finding, not "missing". - In-repo version consistency — manifest, README version badge, newest
CHANGELOG entry and the git tag must agree. An untagged repo
SKIPs the tag comparison rather than failing it. - Badge honesty — a static badge asserting a test, build or coverage run is a claim dressed as evidence. Version, licence and platform badges assert no run and are fine.
- Install truth, not just install syntax — the marketplace URL in the install
block must be the real one (offline, against the register), and the plugin must
actually be pinned in the catalog (one call;
SKIPif unreachable). A perfectly formedclaude plugin install x@mktfails silently whenxwas never pinned, and that is the single most disqualifying thing a repo can publish. - Boilerplate, licence-claim and relative-link checks.
- The skill (
skills/repo-standard/) — the judgement the script cannot encode: what a description should say, why the summary card must never be used to verify one, what not to retrofit, and where the per-repo boundary is. - Link level follows the reader. A dead relative link in a root document —
README, CHANGELOG, SECURITY — is an
ERROR: it is in the shop window. The same link below the root is aWARN. Measured across seventeen repositories: 30 of 43 findings sat inshared/,docs/plan/and.claude/— session plans, agent working files, and path-traversal test fixtures whose targets are invalid on purpose. All 30 wereERRORs, which is how a gate gets switched off. Only the level moves; every finding is still reported with its file and line. - The repo name comes from the remote, not the directory.
catalog/is the working directory of the repo namedktg-plugin-marketplace. Reading the basename left itREPO-UNREGISTEREDwith zero checks run — against the one repo every catalog rule depends on. The scp form the forge's clone button hands out is handled, and a bare host is not a repo name. - 84 tests over the pure classifiers, using measured false positives as reference fixtures.
Notes
- Descriptions are measured in codepoints — not bytes, and not UTF-16 units. The same string measures 248 / 249 / 253 across those three yardsticks when it contains an astral character.
enabledPluginsinsettings.jsonis treated as a legitimate second install form. The gate requires a CLI command as well, and never reports the JSON form as the defect.- Two network calls, both anonymous: the org listing and the catalog manifest.
Per-repo fetching trips the forge's rate limiter, so neither is ever done per
repository.
--offlineskips both, and the checks that needed them reportSKIPrather than passing. CONTRIBUTING.md,CODE_OF_CONDUCT.mdandMAINTAINERS.mdare required by no class: the project is solo-maintained and publishes that stance. This is not a rule against having them — files already present are a cleanup decision, not a gate finding.SECURITY.mdis unaffected; it exists for the outsider who finds a hole.- There is no CI badge because there is no CI: the forge has no Actions runner registered. The substitute is one command from a clean clone, stated honestly. A badge asserting the test count would be the very anti-pattern the gate flags, and an earlier draft of this README carried exactly that.
- The link and boilerplate checks ignore fenced blocks and inline code spans. Documentation about regexes and placeholders is full of text that is a markdown link to a naive scanner — the first version produced about thirty findings against a real repository and every one was noise.
- Relative links resolve against the file they appear in, not the repo root.
- Indented text counts as a code block only when a blank line opens it, and then continues while the indent holds. The first rule alone made links inside nested list items invisible; the second alone let everything after a block's first line leak back in. Both were silent false passes, which is worse than noise — the second was caught by the gate on this plugin's own SKILL.md.
- A README H1 that differs from the repo name is a
WARN, not anERROR. The thread that has to hold is description == catalog == opening line, and the H1 is none of those three; a human title is a naming choice the operator owns. A missing H1 is still anERROR. - No hook ships in this release. A blocking gate has to be precise enough not to fail a correct repository first.