repo-standard/CHANGELOG.md
Kjell Tore Guttormsen 6b1db0096e feat(gate): install truth, honest badges anywhere, and two stripCode bugs
Install truth is the brief's first control and the gate only checked
syntax. Now: the marketplace URL must be the real one (offline, from the
register), and the plugin must actually be pinned in the catalog (one
call, SKIP if unreachable). A well-formed `claude plugin install x@mkt`
fails silently when x was never pinned.

This makes the gate block ITSELF until publication finishes - the run
against this repo now has exactly one ERROR, and it is true: repo-standard
is not in the catalog yet. That is the post-publish acceptance test,
enforced mechanically instead of remembered.

Badge honesty no longer keys on img.shields.io. A self-hosted SVG asserts
the same unverified thing, and the README claimed the general rule while
the code checked one host.

Two stripCode bugs, both silent false passes:
- 4-space indent treated as code unconditionally made links inside nested
  list items invisible. Fixed by requiring a blank line to OPEN a block.
- That fix alone ended the block after line 1, so multi-line indented
  templates leaked back into scanning. Caught by the gate on this repo's
  own SKILL.md, which shows a README template containing a CHANGELOG link.
A block now opens on a blank line and continues while the indent holds.

Also corrected two claims in this README: it said "one network call"
when there are two, and it still argued against a CONTRIBUTING using
reasoning the solo-maintainer section had already replaced.

77 tests. llm-security regression: still zero link and boilerplate noise.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WYJ3FHLtVgzFXMZ6UF598h
2026-07-27 16:13:17 +02:00

5.3 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 tagged ERROR/WARN/SKIP/OK, exit 1 on ERROR. Five checks: README first screen, install block, files required by the repo's class, open/<name> references, 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 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; 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.
  • 77 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.
  • The org listing is read in one call, anonymously. Per-repo fetching trips the forge's rate limiter.
  • 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.