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
384 lines
16 KiB
JavaScript
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');
|
|
});
|