`VERSION-UNAVAILABLE` (SKIP/notRun) becomes `VERSION-NONE` (OK). A repo that claims no version in any of the four places one can be written down has not left a check un-run — the check ran, saw all four, and found no subject. That is the shape `checkReadmeLanguage` has always answered with OK. 0.8.0 deferred this and recorded the reason in the engine: re-levelling "moves a repo's status". Measured false across 19 clones — an added OK cannot worsen the worst *judged* finding, and all three repos emitting the code already read OK. Status moves only for a repo whose entire finding set was skips. OK cannot bless a real gap here: no class requires a version file, and a `plugin` missing its manifest is an independent FILE-MISSING ERROR. Renamed, not just re-levelled: `-UNAVAILABLE` is this engine's naming for a notRun skip, and one OK-level `-UNAVAILABLE` would mislead exactly the reader this change serves. A source scan keeps the old name out. A/B sweep, both engines offline, 19 clones: 223 judged findings, every status and buckets identical; 3 conversions (notChecked 14→13, 3→2, 14→13), byDesign untouched. 170 tests. `--refresh`: register 21 = forge 21. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CTNGvxzCLZp3UXfibYG4kb
16 KiB
| name | description | version |
|---|---|---|
| repo-standard | 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. | 0.2.2 |
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 (not judged —
in one of two ways, see below), OK. Exit 1 on any ERROR. Add --offline to skip the two
network calls, --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 did not judge the
thing. Say which, and say which KIND — since 0.8.0 there are two, and they are
not interchangeable:
NOT CHECKED(skips.notRun) — the gate could not see enough. An unreachable forge or catalog, an unregistered repo, a repo with no tags. A re-run or an operator action turns it into a verdict, so it belongs in your report even when the status is green.NOT JUDGED(skips.byDesign) — the gate saw it and declined on purpose. A link leaving the repository, a dead link inside a fixture path. Nobody has an action. Reporting these as outstanding work is how a clean repo gets rewritten for nothing.
The inverse error is reporting an OK as an un-run check. A check that ran and
found no subject is a verdict, not a skip: VERSION-NONE ("no version
claimed anywhere") and LANGUAGE ("no running prose to judge") are OK and
carry no action. VERSION-NONE was VERSION-UNAVAILABLE/notRun before 0.9.0
— if you see the old code, the engine is stale; see the version note below.
That applies hardest when the repo's own status is green. Since 0.7.0 a SKIP
no longer outranks an OK in the status line, so a repo reads OK · 3 not run
rather than SKIP. The summary line carries only the notRun count — a repo
whose every skip was deliberate prints an unqualified verdict. The line's
silence is not proof there was nothing to say: read the NOT JUDGED block, or
skips.byDesign in --json, before you tell anyone a repo was fully judged.
Confirm the version before you trust a green run. Measured 2026-08-04:
${CLAUDE_PLUGIN_ROOT} resolved to a cached 0.1.1 in a live session while
0.2.0 was installed and the catalog pinned it — same instruction, same
variable, wrong engine, and nothing in the output said so at the time. Two
repos proved it by running both versions against the same checkout: 0.1.1
resurrected three findings 0.1.2/0.1.3 had already fixed. The header line
and --json output now both carry repo-standard v<version> — read it, and
if it does not match what the catalog pins (ktg-plugin-marketplace's
marketplace.json, or ask the operator), say so instead of reporting the run
as clean.
Report in buckets, not in a flat list. Every finding also carries broken
(a stranger is blocked or misled), missing (an expected artefact is absent) or
weakening (present, but reads as amateur). That is the order the work actually
gets done in, and it is more useful to a reader than severity alone. The two
axes are independent: a README opening line that contradicts the published
description blocks nobody and is still an ERROR.
Before you trust a run, look at the noise
The first version of the link check produced about thirty findings against a
real repository and every single one was noise: regexes inside code spans that
are [...](...) to a naive scanner, file: URLs, and relative links compared
against the repo root instead of the directory they sit in. The check now
strips code and resolves properly.
The lesson generalises, so apply it to your own reading: when a check fires many times in one repo, suspect the check before the repo. A gate that is wrong this often teaches people to ignore it, which is worse than not having it at all. If you find a new noise source, fix the classifier and add the case as a fixture — do not tell the user to ignore some of the output.
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 ROADMAP from a five-line profile. That is how a gate teaches people to switch it off.
Traits are a second axis. Class is structural — readable off the catalog and
the remotes. A trait is about what the code does, which no remote knows.
security attaches what a tool owes once it handles untrusted input: a
SECURITY.md with a channel someone actually reads, and limitations stated with
their mechanism. Which repos carry a trait is the maintainer's judgement; do not
add or remove one on your own initiative, propose it.
Who the reader is decides what is required
This project is solo-maintained, and that settles a whole category. Documents
written for contributors — CONTRIBUTING.md, CODE_OF_CONDUCT.md,
MAINTAINERS.md, PR templates, CLA/DCO — are required by no class here, because
there are no contributors and the published stance says so plainly. A code of
conduct with an unattended placeholder address is worse than none: it is a
visible unfinished template.
Documents written for consumers and outsiders are completely unaffected by
that, and working alone is never a reason to skip them: SECURITY.md exists for
the stranger who finds a hole, LICENSE for the one deciding whether they may
use it, non-goals and limitations for the one deciding whether it fits.
Do not turn this into a rule against having those files. A CODE_OF_CONDUCT.md
already sitting in a repo is a cleanup decision for the operator, not a gate
finding.
Badges, and the one that is a lie
Only badges that measure something. A static image reading tests: 642 passing
is a claim dressed as evidence, and the gate flags it — an early draft of this
plugin's own README carried exactly that, which is how it got caught. Version,
licence and platform badges assert no run and are fine as static images.
There is no CI in this organisation: the forge has no Actions runner registered. So do not add a CI badge, and do not pretend. The honest substitute is a single command that runs the whole suite from a clean clone, stated in the README along with the fact that nothing runs it automatically. Verifiability is the goal; CI is one mechanism for it, and it is not available here.
Diagrams — capability is not justification
Mermaid renders in a README on this forge. That was verified on the live
instance rather than inferred: the published voyage README yields two
div.mermaid-block containers holding real SVG. It needs no committed image and
no hand-written iframe, because the forge injects its own renderer.
That is the whole of what the evidence supports — availability. Every claim about visual content failed verification: that images are rare and therefore differentiating, that static images outperform GIFs, that screenshots correlate with anything. There is no evidential basis for a rule about diagrams, screenshots or terminal recordings, so there is no engine check and there will not be one until that changes. Adding a diagram may still be right. It is taste, it has to be argued as taste in the specific repo, and the argument has to say what this reader gains.
Measured, for context and not as a target: across all eighteen READMEs, every
single ![...] resolves to a badge. The org has no real images at all. That is a
description of where things stand, not a deficit to close — inverting a
measurement into a requirement is the trap this whole research line kept
falling into.
What can be judged is a diagram that already exists. Rendering and rendering
well are separate questions, and the org has the gap on display: the second
voyage diagram occupies 1,459 px of vertical space and wraps node text
mid-word. The other one on the same page is 191 px. At the larger size it is not
read, it is scrolled past.
So when a repo has a diagram, or you are adding one:
- Height before beauty. Past roughly one screen it has stopped explaining and
started interrupting. Prefer
flowchart LRtoTDonce the chain runs beyond about five nodes — vertical is the axis that gets away from you. - Short node labels. Mid-word wrapping is the visible symptom of labels written as sentences. The sentence belongs in the prose underneath.
- A diagram earns its place by replacing prose, not by accompanying it. Two descriptions of one thing is the same duplication the changelog rule catches, drawn instead of written.
- Watch the source length.
MERMAID_MAX_SOURCE_CHARACTERSis a per-instance limit, and exceeding it degrades silently to a plain code block — the reader gets raw Mermaid and nothing anywhere reports an error. - No dark-mode image trick. GitHub's
#gh-dark-mode-onlyfragment landed in Gitea 1.26.0; this instance is built on gitea-1.22.0, so both variants stack and the reader sees two images. Mermaid, drawn by the theme, is the one visual that sidesteps the problem entirely. - Judge it published. All of the above is about the rendered result, and a local preview is a different renderer.
Keep the boundary: the gate reports nothing about visuals. Everything in this section is advice you give a human, never a finding you file.
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 1–25. Nobody rewrites a 930-line body, and the gate does not ask you to.
# <name>
<one line — identical to the forge description>
<2–4 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.