feat(repo-standard): v0.1.0 - per-repo gate for the open/ standard

Five checks a single repository can answer on its own: README first
screen, install block, files required by its class, open/<name>
references, description length. Pure classifiers with I/O resolved into
their input, mirroring check-versions.mjs; ERROR/WARN/SKIP/OK, exit 1
on ERROR. 32 tests.

The reference check has THREE outcomes: "matches no repo" (ERROR) is
separate from "matches a known non-repo" (WARN). Sharing an outcome
would let real dead links hide inside correct text. Only names in URL
position count, and .git is normalised first - without that a raw scan
turns 3 dead names into ~20.

enabledPlugins is treated as a legitimate second install form; what the
gate requires in addition is a CLI command. The JSON form is never
reported as the defect.

STATE.md is gitignored from this first commit - public remote.
No hook yet: a blocking gate must first be precise enough not to fail a
correct repository.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WYJ3FHLtVgzFXMZ6UF598h
This commit is contained in:
Kjell Tore Guttormsen 2026-07-27 09:10:46 +02:00
commit 816ba97c63
11 changed files with 1319 additions and 0 deletions

View file

@ -0,0 +1,165 @@
---
name: repo-standard
description: >-
Check and fix one repository against the org's presentation standard — README
first screen, install block, required files for its class, dead `open/<name>`
references, and description length. Use when the user asks to "check this repo
against the standard", "run repo-standard", "is this repo compliant", "fix the
README first screen", "the install instructions are incomplete", "check for
dead repo references", "why does this repo look abandoned", or before
publishing/releasing a repo to the org. Also triggers on Norwegian phrasings:
"sjekk repoet mot standarden", "er dette repoet i orden", "rydd opp i README",
"fiks install-blokka", "finn døde repo-referanser", "gjør repoet presentabelt".
Trigger when someone is about to release, publish, or hand over a repository
and wants its public surface to hold up.
version: "0.1.0"
---
# repo-standard — the per-repo gate
This skill checks **one repository** against the standard for its class, and
helps fix what it finds. The script is the engine; this file is the judgement
the script cannot encode.
## Run the gate first, always
node "${CLAUDE_PLUGIN_ROOT}/scripts/repo-standard-check.mjs" --dir "$PWD"
Findings are `ERROR` (blocks), `WARN` (look, then decide), `SKIP` (the check
could not run), `OK`. Exit 1 on any ERROR. Add `--offline` to skip the one
network call, `--json` for machine output, `--refresh` to compare the bundled
register against the live org listing.
**Never report a `SKIP` as a pass.** A SKIP means the gate could not see enough
to judge — an unreachable forge, a repo missing from the register. Say which.
## What it measures, and what it cannot
The gate sees one repo. Every finding in the census that mattered came from
measuring across eighteen. `llm-security`'s README looks correct from the
inside: it has a Quick Start, an Install heading, a code block. It is only wrong
once eleven repos are compared and one of them turns out to do install
completely.
So: **divergence across the org is not this skill's job.** Zero topics across
all repos, three competing install forms, README release notes duplicating a
CHANGELOG that most repos have — none of that is visible from in here. Those
checks live where the org is enumerated, not in a per-repo gate. If you suspect
a cross-repo problem, say so and stop; do not approximate it from one repo.
## The class decides what is required
The class is read off the catalog and the remotes — it is structural, not a
judgement call. `register/repos.json` holds it.
| Class | Install form |
| --- | --- |
| plugin | `marketplace add` **plus** a CLI install command |
| catalog | `marketplace add` only — it *is* the marketplace |
| shared-asset | how to vendor it; never a plugin install line |
| standalone | pip/uv |
| org-profile | no install section |
A flat standard across all classes would demand a CONTRIBUTING from a CSS
library that takes no contributions and a ROADMAP from a five-line profile.
That is how a gate teaches people to switch it off.
## Two things about the install block worth knowing before you edit one
**`enabledPlugins` is a legitimate second form, not a defect.** Most plugin
READMEs offer it ("Or enable directly in `~/.claude/settings.json`"), and a
reader who scrolls to it has a complete, working path. What the gate requires is
a **CLI command** as well, because an agent handed "install this" reaches for the
CLI and otherwise finds `marketplace add` and nothing after it. Require the
command; welcome the JSON beside it. Never treat the JSON as the failure.
**`marketplace add` rejects `ssh://`.** It answers `Invalid git URL`, and the
message never mentions the protocol. The forge UI's clone button hands out
exactly that URL, so this is a trap people walk into rather than a mistake they
make. Always write the `https://` form.
**Keep the block parametric.** The marketplace name and URL come from the
register, not from a hardcoded string. A repo distributed through a different
marketplace — including a private one — needs its own values, and a public skill
cannot carry private marketplace names in the first place.
## Fixing the first screen
Only lines 125. Nobody rewrites a 930-line body, and the gate does not ask you to.
# <name>
<one line — identical to the forge description>
<24 lines: which problem it solves, who it is for>
## Install
<the block for this class>
## Requirements
## What it does
## Non-goals
…rest unchanged…
## Changelog
See [CHANGELOG.md](CHANGELOG.md).
The opening line is not decoration: it makes description == catalog == README,
which is the only place a machine can check that the three agree. `## Install`
on a fixed heading is what agents pattern-match on — position and predictability
beat brevity for that reader. And **Non-goals answers "is this for me?"** better
than any feature table; almost no README answers it at all.
**Release notes do not belong on the first screen.** A blockquote packing five
versions before the reader knows what the thing *is* both duplicates the
changelog and points at it. Move it under `## Changelog` as a link.
**What not to retrofit:** inline version annotations inside feature tables —
`(v4.1.0)`, "since v2.4.0" — stay. They are real work and they help a reader who
has already installed. The rule applies to new ones: do not add more.
## Dead references — three outcomes, never two
The link check separates "matches no repo" (ERROR) from "matches something that
is deliberately not a repo" (WARN). Keep them separate when you report, too. If
they collapse into one number, a real loss hides inside a pile of correct text.
Names in **URL position only** are references. A repo-shaped string in a path, in
running prose, or as a directory name is not a broken link — and in the measured
cases that text was correct and is *supposed* to stay correct. Do not "fix" it.
Before calling a reference dead, normalise the `.git` suffix. A raw grep once
turned three real dead names into about twenty.
## Descriptions
Written for someone who has never seen the repo, saying what it does and who
it is for. No sales language: "fully", "without exception", "everything from
the terminal" are red flags in a technical text.
Length is bounded and measured in **codepoints** — not bytes, not UTF-16 units.
The same string can measure 248 / 249 / 253 across those three yardsticks when
it contains an astral character like `👉`. An em-dash costs three bytes but one
codepoint, so it only ever exposed the outer layer.
**Never verify a description against the repo summary card.** It is server-side
cached with an undocumented TTL, measured unchanged for more than six hours
after a write. Check the API, or `og:description` in the HTML. A card that still
shows the old text is not a failed write, and re-writing it is how you turn a
cache into an outage of your own making.
## ROADMAP — not required, and not automatic
No class requires one. They are absent everywhere today, and a roadmap is a real
judgement about where a repo is going, not a template.
When one is written, it is the **published, sanitised** derivation of the repo's
own next-step block. **`STATE.md` must never reach a public surface.** Draft
from it, have a human approve, then publish. Never automatically.
## The boundary this skill will not cross
Whether to rename a repo, and whether a given roadmap is real or ceremonial, are
operator decisions. Bring the evidence; do not decide.
And **record findings before fixing them**. Patching while measuring is how the
inconsistency being cleaned up got there in the first place. Run the gate, report
what it says, then fix — in that order.