Commit graph

12 commits

Author SHA1 Message Date
10ad1254ab feat(engine)!: SKIP stops outranking OK, coverage gets its own axis
A repo's `status` is now the worst JUDGED finding, and `SKIP` only when
nothing was judged. `SKIP` used to rank between `OK` and `WARN`, so one
un-runnable check spoke for every check that ran: 0 ERROR, 0 WARN and a
dozen OK headlined as "skipped". Five repos in org-ops census 05, `okr`
among them with the most OK in the org, reading as unread.

"`SKIP` is never a pass" survives in the half of the rule that carries
it — an unregistered repo, or an empty finding set, still says SKIP,
because there is nothing else to be worst of.

Fixing the status alone would have traded "clean repos look skipped" for
"skipped checks look clean". So `notChecked` rides beside it: in --json,
and as a `· N not checked` qualifier on the summary line. Absent means an
older engine, not zero.

Measured across all 21 local clones from ONE saved sweep, so before and
after come from the same findings rather than two sweeps of a moving org:
343 findings before, 343 after. 8 repos moved, every one SKIP -> OK.
1 ERROR and 3 WARN before, 1 ERROR and 3 WARN after — the counts that
decide whether a repo needs work did not move.

BREAKING: consumers reading `.status` see a changed value domain.

147 -> 154 tests.
2026-08-09 21:29:08 +02:00
5884a64e54 feat(register): a decided title, and an org-profile that stops lying
Three changes at the register/engine boundary, all agreed with org-ops
after census 05 and all about a check missing a place to record a
legitimate exception.

`titles`: an optional per-repo README title. Set, the H1 matches it and
is OK; unset, the WARN stands as before. A human title was already this
engine's stated position and rds-v1's prescription, but a decided YES had
nowhere to live, so the same 6 WARNs were reported three censuses running
and would have been reported forever. Five registered, each H1 read from
the repo rather than copied from the census; `ai-psychosis` deliberately
left out so the one repo where a reader cannot connect title to name
stands alone. Measured across 21 local clones: 6 WARN before, 1 after,
nothing else moved.

`readme_desc_match: false` on the org-profile class: for an ordinary repo
the README opening and the forge description describe the same subject
and equality is right; for this class they do not — the README is the
org's landing page, the forge text describes the repo. The equality is
what does not apply, not either text. Class data, not a hardcoded name,
and the exemption is RECORDED as an OK naming its reason, not dropped.
`.profile` went ERROR to 0 ERROR / 0 WARN; the same README under a plugin
class is still an ERROR.

`engineCommit`: the version names a file, only the sha names the code. A
sweep stamped 18 files 0.4.0 while four carried a 0.5.0-only finding —
feature and version bump are two commits, so the stamp lied without being
broken. Present-and-null when underivable, never absent: an absent key
means an older engine, null means this one ran without a HEAD to read.

135 to 147 tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NELsvPY5gnJjN3esdhWYWC
2026-08-09 21:14:43 +02:00
63c75d841c chore(release): v0.5.0, since LINK-INTERNAL-FIXTURE is a new check 2026-08-09 14:31:55 +02:00
43a8d28f00 chore(release): v0.4.0, since LINKS-OPEN-REFS is a new check
Same precedent as v0.2.0 and v0.3.0: a new check code is a minor bump,
not a patch. Bundles the register row for repo #20, the schemaless-host
fix, the reference dedup and the new OK/SKIP outcomes on checkLinks.

Also records the register-freshness decision in CLAUDE.md: --refresh
runs HERE before every release, and consumers of the register are told
not to check freshness themselves. Twice running a newly published repo
was missing when a census ran, and the cost landed in a DIFFERENT repo
than the stale one — portfolio-optimiser's status line stayed put
through a round in which it fixed everything really wrong with it.
Two owners of one invariant is the drift this register exists to remove.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxP9N3p1fG6UYSB8rATBL6
2026-08-09 14:18:32 +02:00
f28615f3b6 chore(release): v0.3.0, since BADGE-DEAD-LINK is a new check
Same precedent as v0.2.0: a new check is a minor bump, not a patch.
Bundles this session's three fixes (LINK-DEAD false positive,
widened 429 backoff, BADGE-DEAD-LINK) and the tautological-test
correction.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1ZJFViVYpr8cvf4fs91j1
2026-08-04 22:29:02 +02:00
f85b9d3229 fix(engine): print engine version, so a stale plugin cache is visible
Measured 2026-08-04: two repos (llm-security, config-audit) independently
proved the /repo-standard skill had resolved ${CLAUDE_PLUGIN_ROOT} to a
cached 0.1.1 while 0.2.0 was installed and the catalog pinned it — same
instruction, same variable, wrong engine. 0.1.1 has neither BADGE-COUNT nor
README-LANGUAGE, so a broadcast recommending the skill produced clean-looking
runs that could not have found what they were sent to find.

The header line and --json output now carry `repo-standard v<version>`
(headerLine/withEngineVersion, both pure and unit tested). SKILL.md tells the
reader to confirm it against the catalog pin before trusting green. The
stale-cache resolution itself is the harness's, not this repo's — not fixed
here, only made visible instead of silent.

TDD: 4 new tests. 111/111 green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01496ZWasKPnA627crFBXWhe
2026-08-04 13:12:29 +02:00
d1b6274924 fix(engine): retry on 429 instead of a false SKIP, and correct the call count
Measured 2026-08-04: 13 script invocations in one shell loop tripped an
anonymous Forgejo rate limit at 26 requests, because each invocation makes
TWO calls (org listing + catalog marketplace.json), not the ONE this repo's
own CLAUDE.md claimed. That line went stale when INSTALL-TRUTH added the
second call and nobody updated the count it depended on.

fetchWithRetry wraps both calls, honoring Retry-After on HTTP 429 instead of
silently falling back to SKIP. TDD: 5 new tests inject a fake fetch and sleep
to drive the retry/backoff/give-up paths without touching the network.

A sweep across every repo still doesn't belong in this engine — that's
org-ops's job by this file's own header — but a single repo's self-check
should not read as broken just because the forge was briefly busy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01496ZWasKPnA627crFBXWhe
2026-08-04 12:12:49 +02:00
75f2149761 chore(release): v0.2.0, since new checks are a minor and the ref is a pointer
BADGE-COUNT and README-LANGUAGE are additions, so this is a minor rather than a
patch. The catalog ref still sat on v0.1.1 against a released v0.1.3; bumping it
to v0.2.0 clears that lag in the same move, because a ref points, it does not
queue.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mf1zhujv5QjYuAn1a9HcgW
2026-08-04 09:55:21 +02:00
5eba10acdd fix: three more measured false positives, all reported the same day v0.1.2 shipped
- extractChangelogTop truncated PEP 440 pre-release versions (0.5.0a2 -> 0.5.0),
  so VERSION-CHANGELOG disagreed with VERSION-TAG over a version everything
  already agreed on. Reported by llm-ingestion-okf with a repro.
- BADGE-STATIC-CLAIM treated a bare `status` badge as a run claim, same as
  tests/build/CI. A self-declared maturity label asserts no run, same class
  as version/licence/platform. Reported by llm-ingestion-pipeline-security.
- BOILERPLATE flagged FIXME when a scanner's own docs named the TODO/FIXME
  convention rather than an instance of it. Reported by config-audit.

92 tests green, up from 86.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uwwfdmrfnp7FuGQ4z25RKH
2026-08-03 22:10:17 +02:00
3c2a535297 fix(links): a directory link is not a missing file, so a tracked dir now resolves
`checkInternalLinks` compared a link's resolved target only against `present`
(tracked files), so `[x](dir/)` was always LINK-INTERNAL-MISSING even when
every file under it was tracked. Reported by portfolio-optimiser-claude with a
minimal repro; the same defect inflated ERROR counts in voyage, linkedin-studio
and portfolio-optimiser — 12 of the org's 71 measured ERRORs were this one
check, not twelve repo problems.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uwwfdmrfnp7FuGQ4z25RKH
2026-08-03 21:57:53 +02:00
0945e88598 chore(release): v0.1.1, so the pinned tag serves the corrected count
The 0.1.0 entry said eleven checks; there are twelve, and both the code and
the README table already said so. 2963f4f fixed the entry in place but landed
after the tag, so the catalog's pin kept serving the wrong count.

Documentation only: scripts/ and register/ are unchanged from v0.1.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Wuy8mxQj8Zt4z23hiRjiN
2026-08-03 20:57:56 +02:00
816ba97c63 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
2026-07-27 09:10:46 +02:00