# repo-standard Per-repo gate for the open/ presentation standard: README first screen, install block, files required by the repo's class, and dead repo references. A repository can be substantially good and still read as abandoned. The gap is almost never the code — it is the first screen, an install path that stops halfway, and references to a name that was retired two renames ago. This plugin checks that surface in one repository and reports what it finds. > **Solo-maintained, fork-and-own.** This plugin is a starting point, not a vendor product. Issues are welcome as signals; pull requests are not accepted. See the [marketplace governance](https://git.fromaitochitta.com/open/ktg-plugin-marketplace/src/branch/main/GOVERNANCE.md) for the full model. *AI-generated: all code produced by Claude Code through dialog-driven development.* ![Version](https://img.shields.io/badge/version-0.1.0-blue) ![Platform](https://img.shields.io/badge/platform-Claude_Code_Plugin-purple) ![Skills](https://img.shields.io/badge/skills-1-orange) ![Tests](https://img.shields.io/badge/tests-34-green) ![License](https://img.shields.io/badge/license-MIT-lightgrey) ## Install Use the `https://` form. The forge UI's clone button hands out an `ssh://` URL, and `marketplace add` answers it with `Invalid git URL` — a message that never mentions the protocol. ```bash claude plugin marketplace add https://git.fromaitochitta.com/open/ktg-plugin-marketplace.git claude plugin install repo-standard@ktg-plugin-marketplace ``` Or enable it directly in `~/.claude/settings.json` — a working second path, not a replacement for the two commands above: ```json { "enabledPlugins": { "repo-standard@ktg-plugin-marketplace": true } } ``` ## Requirements Node 18 or newer. No dependencies. The one network call — the org listing, used to read a repo's published description — reads anonymously, so it needs no token; `--offline` skips it. ## What it does Run it inside a repository: ```bash node scripts/repo-standard-check.mjs --dir "$PWD" ``` It checks five things, and the repository's **class** decides what each one means: | Check | What fails it | | --- | --- | | First screen | no H1 on line 1, or the line under it is not the published description. An H1 that merely differs from the repo name is a `WARN` — that is a naming choice, not a defect | | Install block | the form for this class is missing, incomplete, or shown over `ssh://` | | Required files | a file this class needs is absent | | References | an `open/` in URL position resolves to nothing | | Description | empty, or past the length bound | Findings are `ERROR`, `WARN`, `SKIP` or `OK`; the process exits 1 on any `ERROR`. A `SKIP` means the check could not run — an unreachable forge, a repo that is not in the register. It is not a pass, and the output says which. ### The class decides what is required The class is read off the catalog and the remotes; it is structural, not a judgement. It lives in `register/repos.json`. | Class | Install form | Requires | | --- | --- | --- | | plugin | `marketplace add` **and** a CLI install command | README, LICENSE, CHANGELOG, plugin manifest | | catalog | `marketplace add` only — it *is* the marketplace | + GOVERNANCE, CONVENTIONS | | shared-asset | how to vendor it; never a plugin install line | README, LICENSE | | standalone | pip/uv | README, LICENSE | | org-profile | none | README | A flat standard across every class would demand a CONTRIBUTING from a CSS library that accepts no contributions, and a roadmap from a five-line profile. That is how a gate teaches people to switch it off. ### Three outcomes on references, not two "Matches no repository" and "matches something that is deliberately not a repository" are different findings. The second class is real and it is common: a retired name kept alive on purpose in prose, a reserved namespace occupying a repo-shaped path, a published package name that was never a repo. If those share an outcome with genuine dead links, the genuine ones hide inside a pile of correct text. Only names in **URL position** are treated as references, which excludes prose, paths and directory names in one move. The `.git` suffix is normalised first — without that, a raw scan turns three dead names into about twenty. ## Non-goals - **Anything requiring a view across every repository at once.** This gate sees one repo. A README can look correct from the inside and only turn out wrong when a dozen are compared. Org-wide divergence is measured where the org is enumerated, not here. - **Fixing while measuring.** It records findings; you fix them afterwards. Patching under measurement is how inconsistency accumulates unnoticed. - **Deciding whether to rename a repo, or whether a roadmap is real.** Those are operator calls. The gate brings evidence to them. - **Blocking commits.** There is no hook. A gate that fails a correct repository is the mechanism that gets gates switched off, so this one earns that role before it takes it. ## Tests ```bash npm test ``` 34 tests over the pure classifiers. The reference fixtures are the measured false positives that produced the three-outcome rule, each with its expected verdict. ## Changelog See [CHANGELOG.md](CHANGELOG.md).