repo-standard/scripts/repo-standard-check.test.mjs
Kjell Tore Guttormsen 2357771587 fix(gate): a differing README H1 is a WARN, not an ERROR
Measured against the live repos: okr opens `# OKR for Public Sector`
and claude-design `# Claude Design Facilitator`. Neither breaks the
thread the contract exists to protect - description == catalog ==
opening line - because the H1 is none of those three. Failing them
would be the gate that stops a correct repo, which is what teaches
people to switch gates off.

A missing H1 stays an ERROR, and a differing one no longer short-
circuits the description check.

Validation against three cases the census measured by hand, all
reproduced independently: okr (neither install line), claude-design
(slash form, no marketplace add), repo-mailbox (install correct,
first screen wrong). 34 tests.

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

384 lines
16 KiB
JavaScript

// Tests for the repo-standard gate.
//
// The pure classifiers are the unit under test — the I/O shell (inspectRepo/runGate)
// is exercised against a live checkout by the CLI, not here.
//
// The link-check fixtures are the six measured false positives from the census.
// They are the reason this gate has three outcomes instead of a boolean.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import {
countCodepoints,
normalizeRepoRef,
extractOpenRefs,
classifyRef,
checkLinks,
checkDescription,
checkFirstScreen,
checkInstallBlock,
checkRequiredFiles,
classifyRepo,
levelOf,
} from './repo-standard-check.mjs';
const REGISTER = {
org: 'open',
marketplace: {
name: 'ktg-plugin-marketplace',
url: 'https://git.fromaitochitta.com/open/ktg-plugin-marketplace.git',
},
repos: {
'llm-security': 'plugin',
'repo-mailbox': 'plugin',
'repo-standard': 'plugin',
'ktg-plugin-marketplace': 'catalog',
'playground-design-system': 'shared-asset',
'.profile': 'org-profile',
'llm-ingestion-pipeline-security': 'standalone',
},
non_repos: {
coord: 'Retired repo name, deliberately still alive in prose: the CLI, the mailbox root and CLAUDE_COORD_DIR kept it — they are the transport protocol, not the product.',
_broadcast: 'reserved engine namespace',
'llm-ingestion-guard': 'package name, not a repo',
'claude-code-llm-security': 'pre-split name of llm-security',
},
classes: {
plugin: {
required_files: ['README.md', 'LICENSE', 'CHANGELOG.md', '.claude-plugin/plugin.json'],
install: 'plugin',
},
catalog: {
required_files: ['README.md', 'LICENSE', 'GOVERNANCE.md', 'CONVENTIONS.md', '.claude-plugin/marketplace.json'],
install: 'catalog',
},
'shared-asset': { required_files: ['README.md', 'LICENSE'], install: 'vendor' },
'org-profile': { required_files: ['README.md'], install: 'none' },
standalone: { required_files: ['README.md', 'LICENSE'], install: 'package' },
},
description_max_codepoints: 180,
};
// ---------------------------------------------------------------- measurement
test('countCodepoints measures codepoints, not bytes and not UTF-16 units', () => {
// The em-dash exposes only the byte layer: 3 bytes, 1 codepoint, 1 UTF-16 unit.
assert.equal(countCodepoints('a—b'), 3);
assert.equal(Buffer.byteLength('a—b', 'utf8'), 5);
// 👉 is astral: 1 codepoint but 2 UTF-16 units. This is the layer the em-dash hides.
assert.equal(countCodepoints('👉'), 1);
assert.equal('👉'.length, 2);
});
// ------------------------------------------------------------- ref extraction
test('normalizeRepoRef strips a .git suffix and a trailing slash', () => {
// ~20 "dead" names collapsed to 3 real ones once .git was normalised.
assert.equal(normalizeRepoRef('llm-security.git'), 'llm-security');
assert.equal(normalizeRepoRef('llm-security/'), 'llm-security');
assert.equal(normalizeRepoRef('llm-security'), 'llm-security');
});
test('extractOpenRefs finds names in URL position only', () => {
const text = [
'clone https://git.fromaitochitta.com/open/llm-security.git today',
'see https://git.fromaitochitta.com/open/repo-mailbox/src/branch/main/README.md',
].join('\n');
const names = extractOpenRefs(text).map((r) => r.name);
assert.deepEqual(names, ['llm-security', 'repo-mailbox']);
});
test('extractOpenRefs ignores path position, prose and bare directory names', () => {
// False positives #4, #5, #6 — the text is correct and will STAY correct.
const text = [
'the mailbox root is ~/.claude/coord/_broadcast/inbox/',
'coord is the transport protocol, not the product',
'the catalog lives in ktg-plugin-marketplace/catalog',
'the package llm-ingestion-guard is published from that repo',
].join('\n');
assert.deepEqual(extractOpenRefs(text), []);
});
test('extractOpenRefs handles the ssh scp-style form', () => {
const refs = extractOpenRefs('git@git.fromaitochitta.com:open/llm-security.git');
assert.deepEqual(refs.map((r) => r.name), ['llm-security']);
});
test('extractOpenRefs reports the 1-indexed line of each hit', () => {
const text = 'line one\nline two\nhttps://git.fromaitochitta.com/open/llm-security';
assert.equal(extractOpenRefs(text)[0].line, 3);
});
// ---------------------------------------------- three outcomes, not a boolean
test('classifyRef separates repo, non-repo and unknown', () => {
assert.equal(classifyRef('llm-security', REGISTER), 'repo');
assert.equal(classifyRef('.profile', REGISTER), 'repo');
assert.equal(classifyRef('coord', REGISTER), 'non-repo');
assert.equal(classifyRef('nonesuch', REGISTER), 'unknown');
});
test('a URL-position ref to a known non-repo is a DISTINCT outcome from no match', () => {
// The specification requirement: "no match" and "match on something that is
// not a repo" must never share an outcome, or the loss goes silent.
const bad = checkLinks({ files: { 'README.md': 'https://git.fromaitochitta.com/open/nonesuch' } }, REGISTER);
const odd = checkLinks({ files: { 'README.md': 'https://git.fromaitochitta.com/open/coord' } }, REGISTER);
assert.equal(bad[0].level, 'ERROR');
assert.equal(bad[0].code, 'LINK-DEAD');
assert.equal(odd[0].level, 'WARN');
assert.equal(odd[0].code, 'LINK-NON-REPO');
assert.notEqual(bad[0].code, odd[0].code);
// The reason travels with the finding, so the reader is not sent measuring again.
assert.match(odd[0].msg, /transport protocol/);
});
test('a dead ref names its successor when the register knows one', () => {
const f = checkLinks(
{ files: { 'README.md': 'https://git.fromaitochitta.com/open/claude-code-llm-security' } },
REGISTER,
);
assert.equal(f[0].level, 'WARN');
assert.match(f[0].msg, /pre-split name/);
});
test('the .git suffix does not manufacture a dead reference', () => {
const f = checkLinks(
{ files: { 'README.md': 'https://git.fromaitochitta.com/open/llm-security.git' } },
REGISTER,
);
assert.equal(f.filter((x) => x.level === 'ERROR').length, 0);
});
test('the hidden .profile resolves — the enumerator sees what a glob misses', () => {
const f = checkLinks({ files: { 'README.md': 'https://git.fromaitochitta.com/open/.profile' } }, REGISTER);
assert.equal(f.filter((x) => x.level === 'ERROR').length, 0);
});
// ------------------------------------------------------------- description
test('description length is bounded, measured in codepoints', () => {
assert.equal(checkDescription('a fine description', REGISTER)[0].level, 'OK');
assert.equal(checkDescription('', REGISTER)[0].level, 'ERROR');
assert.equal(checkDescription('x'.repeat(181), REGISTER)[0].level, 'ERROR');
assert.equal(checkDescription('x'.repeat(180), REGISTER)[0].level, 'OK');
});
test('an unavailable description is SKIP, never a pass', () => {
// Offline is not compliance. A check that could not run says so.
const f = checkDescription(null, REGISTER);
assert.equal(f[0].level, 'SKIP');
});
// ------------------------------------------------------------- first screen
test('README line 1 must be the H1, and the description line must match the forge', () => {
const readme = '# repo-mailbox\nA local mailbox for coordination.\n';
assert.equal(
checkFirstScreen({ readme, name: 'repo-mailbox', description: 'A local mailbox for coordination.' })
.every((f) => f.level === 'OK'),
true,
);
});
test('a README whose opening line diverges from the description is an ERROR', () => {
const readme = '# repo-mailbox\nSomething else entirely.\n';
const f = checkFirstScreen({ readme, name: 'repo-mailbox', description: 'A local mailbox for coordination.' });
assert.equal(f.some((x) => x.level === 'ERROR' && x.code === 'README-DESC'), true);
});
test('first-screen description match is SKIP when the forge text is unavailable', () => {
const f = checkFirstScreen({ readme: '# x\nbody\n', name: 'x', description: null });
assert.equal(f.some((x) => x.code === 'README-DESC' && x.level === 'SKIP'), true);
});
test('a missing H1 is an ERROR', () => {
const f = checkFirstScreen({ readme: 'no heading here\n', name: 'x', description: null });
assert.equal(f.some((x) => x.level === 'ERROR' && x.code === 'README-H1'), true);
});
test('an H1 that differs from the repo name is a WARN, not a failure', () => {
// `# OKR for Public Sector` is a naming choice, not a defect: the thread that
// must hold is description == catalog == opening line, and the H1 is none of
// those three. Surface it; let the operator decide.
const f = checkFirstScreen({ readme: '# OKR for Public Sector\nbody\n', name: 'okr', description: null });
assert.equal(f.some((x) => x.level === 'WARN' && x.code === 'README-H1'), true);
assert.equal(f.some((x) => x.level === 'ERROR'), false);
});
test('a differing H1 does not stop the description check from running', () => {
const f = checkFirstScreen({ readme: '# Nice Title\nthe description\n', name: 'x', description: 'the description' });
assert.equal(f.some((x) => x.code === 'README-DESC' && x.level === 'OK'), true);
});
// ------------------------------------------------------------ install block
const MKT = REGISTER.marketplace;
test('plugin install needs BOTH lines: marketplace add and a CLI install command', () => {
const readme = [
'## Install',
'```',
`claude plugin marketplace add ${MKT.url}`,
`claude plugin install repo-mailbox@${MKT.name}`,
'```',
].join('\n');
const f = checkInstallBlock({ readme, name: 'repo-mailbox', klass: 'plugin' }, REGISTER);
assert.equal(f.filter((x) => x.level === 'ERROR').length, 0);
});
test('the slash form counts as the CLI command', () => {
const readme = [
'## Install',
`claude plugin marketplace add ${MKT.url}`,
`/plugin install claude-design@${MKT.name}`,
].join('\n');
const f = checkInstallBlock({ readme, name: 'claude-design', klass: 'plugin' }, REGISTER);
assert.equal(f.filter((x) => x.level === 'ERROR').length, 0);
});
test('enabledPlugins JSON is an ALLOWED ADDITION, never a replacement for the CLI command', () => {
// This is the corrected defect A: 7 of 11 plugin READMEs stop after
// `marketplace add`. The JSON form works and stands in 10 of 11 — what is
// missing is a CLI command, so the contract requires the command and permits
// the JSON alongside it.
const jsonOnly = [
'## Install',
`claude plugin marketplace add ${MKT.url}`,
'Or enable directly in `~/.claude/settings.json`:',
`"enabledPlugins": { "llm-security@${MKT.name}": true }`,
].join('\n');
const f = checkInstallBlock({ readme: jsonOnly, name: 'llm-security', klass: 'plugin' }, REGISTER);
assert.equal(f.some((x) => x.level === 'ERROR' && x.code === 'INSTALL-NO-CLI'), true);
const both = jsonOnly + `\nclaude plugin install llm-security@${MKT.name}\n`;
const g = checkInstallBlock({ readme: both, name: 'llm-security', klass: 'plugin' }, REGISTER);
assert.equal(g.filter((x) => x.level === 'ERROR').length, 0);
});
test('a missing marketplace add is its own finding — okr and claude-design are opposite halves', () => {
const noAdd = ['## Install', `/plugin install claude-design@${MKT.name}`].join('\n');
const f = checkInstallBlock({ readme: noAdd, name: 'claude-design', klass: 'plugin' }, REGISTER);
assert.equal(f.some((x) => x.level === 'ERROR' && x.code === 'INSTALL-NO-MARKETPLACE'), true);
// okr: neither line. Both findings fire — a rule saying "both lines" must not
// hit this repo blind.
const neither = ['## Install', `"enabledPlugins": { "okr@${MKT.name}": true }`].join('\n');
const g = checkInstallBlock({ readme: neither, name: 'okr', klass: 'plugin' }, REGISTER);
assert.equal(g.some((x) => x.code === 'INSTALL-NO-MARKETPLACE'), true);
assert.equal(g.some((x) => x.code === 'INSTALL-NO-CLI'), true);
});
test('the install target must name THIS repo, not another plugin', () => {
const readme = [
'## Install',
`claude plugin marketplace add ${MKT.url}`,
`claude plugin install some-other-plugin@${MKT.name}`,
].join('\n');
const f = checkInstallBlock({ readme, name: 'repo-standard', klass: 'plugin' }, REGISTER);
assert.equal(f.some((x) => x.code === 'INSTALL-NO-CLI'), true);
});
test('ssh in the marketplace add line is an ERROR — marketplace add rejects it', () => {
// Measured end-to-end: `marketplace add ssh://...` → "Invalid git URL".
// The forge UI's clone button hands you exactly that URL.
const readme = [
'## Install',
'claude plugin marketplace add ssh://git@git.fromaitochitta.com/open/ktg-plugin-marketplace.git',
`claude plugin install repo-standard@${MKT.name}`,
].join('\n');
const f = checkInstallBlock({ readme, name: 'repo-standard', klass: 'plugin' }, REGISTER);
assert.equal(f.some((x) => x.level === 'ERROR' && x.code === 'INSTALL-SSH'), true);
});
test('the install block is parametric — a different marketplace passes on its own values', () => {
// wiki-advise lives on the private ktg/ namespace and is distributed via
// `ktg-privat`. A skill that hardcodes the public marketplace produces an
// install line that does not work there — and being public itself, this skill
// cannot carry private marketplace names.
const priv = {
...REGISTER,
marketplace: { name: 'ktg-privat', url: 'https://git.fromaitochitta.com/ktg/ktg-privat.git' },
};
const readme = [
'## Install',
'claude plugin marketplace add https://git.fromaitochitta.com/ktg/ktg-privat.git',
'claude plugin install wiki-advise@ktg-privat',
].join('\n');
const f = checkInstallBlock({ readme, name: 'wiki-advise', klass: 'plugin' }, priv);
assert.equal(f.filter((x) => x.level === 'ERROR').length, 0);
});
test('the catalog needs only marketplace add — it IS the marketplace', () => {
const readme = `## Install\nclaude plugin marketplace add ${MKT.url}`;
const f = checkInstallBlock({ readme, name: 'ktg-plugin-marketplace', klass: 'catalog' }, REGISTER);
assert.equal(f.filter((x) => x.level === 'ERROR').length, 0);
});
test('a shared asset is vendored, not installed — a plugin install line is wrong there', () => {
const asPlugin = `## Install\nclaude plugin install playground-design-system@${MKT.name}`;
const f = checkInstallBlock(
{ readme: asPlugin, name: 'playground-design-system', klass: 'shared-asset' },
REGISTER,
);
assert.equal(f.some((x) => x.level === 'ERROR' && x.code === 'INSTALL-WRONG-FORM'), true);
});
test('.profile needs no install section at all', () => {
const f = checkInstallBlock({ readme: '# .profile\nOrg profile.\n', name: '.profile', klass: 'org-profile' }, REGISTER);
assert.equal(f.filter((x) => x.level === 'ERROR').length, 0);
});
// ----------------------------------------------------------- required files
test('required files are per class, not flat across the org', () => {
const ok = checkRequiredFiles({ present: ['README.md'], klass: 'org-profile' }, REGISTER);
assert.equal(ok.filter((f) => f.level === 'ERROR').length, 0);
const missing = checkRequiredFiles({ present: ['README.md'], klass: 'plugin' }, REGISTER);
assert.equal(missing.some((f) => f.code === 'FILE-MISSING' && f.msg.includes('LICENSE')), true);
});
test('no class requires a ROADMAP — it is 0/18 and belongs to a later step', () => {
for (const klass of Object.keys(REGISTER.classes)) {
assert.equal(REGISTER.classes[klass].required_files.includes('ROADMAP.md'), false);
}
});
// -------------------------------------------------------------- aggregation
test('levelOf ranks ERROR above WARN above SKIP above OK', () => {
assert.equal(levelOf([{ level: 'OK' }, { level: 'WARN' }, { level: 'ERROR' }]), 'ERROR');
assert.equal(levelOf([{ level: 'OK' }, { level: 'WARN' }]), 'WARN');
assert.equal(levelOf([{ level: 'OK' }, { level: 'SKIP' }]), 'SKIP');
assert.equal(levelOf([{ level: 'OK' }]), 'OK');
assert.equal(levelOf([]), 'OK');
});
test('an unregistered repo is SKIP, not a pass — the gate refuses to guess a class', () => {
const r = classifyRepo({ name: 'stranger', files: {}, present: [], description: null }, REGISTER);
assert.equal(r.status, 'SKIP');
});
test('a fully compliant plugin repo classifies OK', () => {
const readme = [
'# repo-mailbox',
'A local mailbox for coordination.',
'',
'Body text.',
'',
'## Install',
`claude plugin marketplace add ${MKT.url}`,
`claude plugin install repo-mailbox@${MKT.name}`,
].join('\n');
const r = classifyRepo(
{
name: 'repo-mailbox',
files: { 'README.md': readme },
present: ['README.md', 'LICENSE', 'CHANGELOG.md', '.claude-plugin/plugin.json'],
description: 'A local mailbox for coordination.',
},
REGISTER,
);
assert.equal(r.status, 'OK');
});