fix(gate): the reader sets a link's level, and a repo's name is its remote

Two defects that only org-wide measurement exposes. Both were found by running
the gate against seventeen repositories, not by reading the code.

Link level follows the reader. 30 of 43 LINK-INTERNAL-MISSING findings sat in
`shared/`, `docs/plan/` and `.claude/` -- session plans, agent working files,
and path-traversal fixtures whose targets are invalid on purpose. All 30 were
ERRORs. portfolio-optimiser scored 19 ERRORs and 15 of them were noise. A gate
that wrong gets switched off, so root documents stay ERROR and everything below
becomes WARN. Only the level moves; the finding keeps its file and line.

The OK line had to move with it: it asserted "every resolvable relative link
resolves" whenever no ERROR was present, which would have printed it beside a
pile of WARNs saying the opposite.

The repo name comes from `git remote get-url origin`. `catalog/` is the working
directory of `ktg-plugin-marketplace`; the basename left it REPO-UNREGISTERED
with zero checks run -- against the one repo every catalog rule depends on. The
scp form is handled because the forge's clone button hands it out, and a bare
host is not a repo name (that test caught a real bug: `https://host/` parsed as
a repo named after the host).

Re-measured: portfolio-optimiser 19 ERROR -> 4, all four genuine. catalog now
reports as `ktg-plugin-marketplace [catalog]` and runs its full rule set.

Still v0.1.0: nothing is pushed, no tag exists, no consumer has seen it.

77 -> 84 tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EeNsGsWukggfmLQ926WZPx
This commit is contained in:
Kjell Tore Guttormsen 2026-08-03 19:53:57 +02:00
commit 9fcceb7522
5 changed files with 143 additions and 6 deletions

View file

@ -49,7 +49,19 @@ First release. Covers the checks that a single repository can answer on its own.
- **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
- **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