# Changelog All notable changes to this project are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning is [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [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 tagged `ERROR`/`WARN`/`SKIP`/`OK`, exit 1 on `ERROR`. Twelve checks: README first screen, install block, install truth, required headings, files required by the repo's class and traits, `open/` 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. `--refresh` compares 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 `.git` suffix is normalised first. - **Two-axis findings** — every `ERROR`/`WARN` carries 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. `security` attaches a `SECURITY.md` requirement and a `## Known limitations` section. - **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 `SKIP`s 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; `SKIP` if unreachable). A perfectly formed `claude plugin install x@mkt` fails silently when `x` was 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 a `WARN`. Measured across seventeen repositories: 30 of 43 findings sat in `shared/`, `docs/plan/` and `.claude/` — session plans, agent working files, and path-traversal test fixtures whose targets are invalid on purpose. All 30 were `ERROR`s, 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 named `ktg-plugin-marketplace`. Reading the basename left it `REPO-UNREGISTERED` with 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. - `enabledPlugins` in `settings.json` is 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. `--offline` skips both, and the checks that needed them report `SKIP` rather than passing. - `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md` and `MAINTAINERS.md` are 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.md` is 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 an `ERROR`. 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 an `ERROR`. - No hook ships in this release. A blocking gate has to be precise enough not to fail a correct repository first. [0.1.0]: https://git.fromaitochitta.com/open/repo-standard/src/tag/v0.1.0