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
This commit is contained in:
Kjell Tore Guttormsen 2026-08-09 21:14:43 +02:00
commit 5884a64e54
8 changed files with 358 additions and 27 deletions

View file

@ -1,6 +1,6 @@
{
"name": "repo-standard",
"version": "0.5.0",
"version": "0.6.0",
"description": "Per-repo gate for the open/ presentation standard: README first screen, install block, files required by the repo's class, and dead repo references.",
"author": {
"name": "Kjell Tore Guttormsen"

View file

@ -4,6 +4,48 @@ All notable changes to this project are documented here.
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
versioning is [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.6.0] — 2026-08-09
### Added
- `titles` in the register: an optional per-repo README title. Set, the H1 is
compared against it and a match is `OK`; unset, the `WARN` stands exactly as
before. A human title was already a valid choice — `docs/rds-v1.md` prescribes
`1. # Title` for every class, not `# repo-name` — but a decided YES had
nowhere to live, so the same 6 `README-H1` WARNs were reported in census 05,
06 and 07 and would have been reported forever. "We decided this is correct"
and "nobody has looked at it" now produce different outcomes. Five titles
registered, each H1 read from the repo rather than copied from the census;
`ai-psychosis` is deliberately left unregistered, so the one repo where a
reader cannot connect title to name stands alone. Measured across all 21
local clones: 6 WARN before, 1 after, no other finding moved.
- `engineCommit` alongside `engineVersion`, in the header line (short) and the
`--json` output (full). The version names a FILE; only the sha names the CODE.
A sweep stamped 18 raw files `0.4.0` while four carried findings from a check
that only exists in 0.5.0 — the feature and the version bump are two commits,
so the worktree held new code under an old number for a window, and the stamp
lied without being broken. Derived from this checkout, no network call. The
field is present-and-`null` when underivable, never absent: an absent key
means an older engine, an explicit `null` means this engine ran and had no
HEAD to read, and a consumer sorting raw files by stamp needs those to differ.
### Changed
- `README-DESC` no longer demands byte equality for the `org-profile` class,
via `readme_desc_match: false` on the class — data in the register, not a
hardcoded name. For an ordinary repo the README opening and the forge
description describe the same subject and equality is right; for this one
class they do not — the README is the organisation's landing page, the forge
text describes the repo. Both are correct about their own subject, so it is
the equality that does not apply. A landing page's opening line also carries a
markdown link while the description field renders as plain text, so passing
the old check would have meant putting raw markdown on a real surface. The
class has one member, so coverage is lost nowhere else, and the exemption is
still RECORDED as an `OK` finding naming the reason rather than dropped.
Measured: `.profile` went from `ERROR` to 0 ERROR / 0 WARN, and the same
README under a `plugin` class is still an `ERROR`.
## [0.5.0] — 2026-08-09
### Added

View file

@ -93,13 +93,38 @@ would recreate, in data, exactly the drift this plugin exists to remove.
- **A repo's name is its remote, not its directory.** `catalog/` holds
`ktg-plugin-marketplace`. The basename left it unregistered with zero checks
run, against the one repo every catalog rule depends on.
- **A decision needs somewhere to live, or the gate repeats itself forever.**
The engine already held that a human README title is the operator's call —
and still warned about it every round, because a YES could not be recorded.
Six warnings, unchanged across censuses 05, 06 and 07. `titles` in the
register is that record: set, the H1 matching it is `OK`; unset, the `WARN`
stands. What the gate must never do is make "we decided this" and "nobody
looked" the same output. The wanted side effect is exposure, not silence —
`ai-psychosis` is deliberately unregistered so it stands alone.
- **An exemption is a finding, not a deletion.** `readme_desc_match: false`
turns off README-DESC equality for a class, and the check still emits an `OK`
naming why. An exception nobody can see reads exactly like a check that
silently stopped running.
- **Class rules live in the register, never as a class name in the engine.**
The `org-profile` exemption is a flag on the class, not `if (klass ===
'org-profile')`. Per-repo copies of a rule are the drift this plugin exists
to remove; a class name hardcoded in a classifier is the same defect one
level up.
- **The version names a file; only the sha names the code.** `engineVersion`
was added because a stale cache served an old engine silently — but a feature
and its version bump are two commits, so a worktree carries new behaviour
under the old number for a window. Measured: a sweep stamped 18 raw files
`0.4.0`, four of them holding findings from a check that only exists in
`0.5.0`. `engineCommit` closes that, derived from the same checkout with no
network call. It is present-and-`null` when underivable, never absent — an
absent key means an older engine, `null` means this one ran without a HEAD.
- **No hook until the rule is precise.** A blocking gate that fails a correct
repository is the mechanism that gets gates switched off.
## Commands
```bash
npm test # 135 tests
npm test # 147 tests
node scripts/repo-standard-check.mjs --dir "$PWD" # gate one repo
node scripts/repo-standard-check.mjs --offline # no network call
node scripts/repo-standard-check.mjs --json # machine output

View file

@ -10,7 +10,7 @@ checks that surface in one repository and reports what it finds.
*AI-generated: all code produced by Claude Code through dialog-driven development.*
![Version](https://img.shields.io/badge/version-0.5.0-blue)
![Version](https://img.shields.io/badge/version-0.6.0-blue)
![Platform](https://img.shields.io/badge/platform-Claude_Code_Plugin-purple)
![Skills](https://img.shields.io/badge/skills-1-orange)
![License](https://img.shields.io/badge/license-MIT-lightgrey)
@ -108,6 +108,39 @@ finding is a `SKIP` — the question is live and unanswered. Where there is no
running prose at all, it is an `OK`: nothing claims a language, and a thin README
is the first-screen check's business, not this one's.
### Registered titles — where a decision gets written down
A README H1 that is a human title rather than the repo name is a naming choice
the maintainer owns, and the standard prescribes `# Title` for every class. But
until a YES could be *recorded*, the gate reported the same six warnings every
round, and there was no way to tell "this was decided" from "nobody has looked".
An optional `titles` entry in the register is that record. Set it, and an H1
matching it is an `OK`. Leave it out, and the warning stands exactly as before.
The point is the asymmetry: once the deliberate titles are registered, the repos
nobody has ruled on are the only ones still warning.
An H1 that matches neither the repo name nor a registered title is still a
warning, and the message names both — that is drift in one of the two, not a
title.
### When equality is the wrong demand
`README-DESC` requires the README's opening line to be the forge description
verbatim, because for an ordinary repo the two describe the same subject and any
gap between them is drift on a published surface.
The `org-profile` class is the one place that premise fails. Its README is the
organisation's landing page; the forge description describes the repository.
Both are correct about their own subject, so it is the *equality* that does not
apply, not either text — and a landing page's opening line carries a link, while
the description field renders as plain text, so satisfying the old check would
have meant putting raw markdown on a real surface.
A class turns the demand off with `readme_desc_match: false` in the register.
The exemption is still reported as a finding that names the reason: an exception
nobody can see is indistinguishable from a check that silently stopped running.
### What is deliberately not required
`CONTRIBUTING.md`, `CODE_OF_CONDUCT.md` and `MAINTAINERS.md` are required by no
@ -147,6 +180,28 @@ Only names in **URL position** are treated as references, which excludes prose,
paths and directory names in one move. The `.git` suffix is normalised first —
without that, a raw scan turns three dead names into about twenty.
### Every run says which engine produced it
The header and the `--json` output carry the engine's version *and* the commit
it ran from:
```
✓ voyage [plugin] — OK (repo-standard v0.6.0 @a7276e6)
```
Both, because they answer different questions. A stale plugin cache once served
an old engine against a current repo and the output looked like a clean pass,
which is why the version is there. But the version names a *file*: a feature and
its version bump are two commits, so a worktree holds new behaviour under the
old number for a window, and a sweep once stamped eighteen files with a version
that predated the check that produced their findings. Only the commit names the
code.
The commit is read from the engine's own checkout, with no network call. When
there is none to read — a vendored copy, an unpacked tarball — the JSON field is
present and `null` rather than missing, so "this engine could not tell you" stays
distinct from "an older engine that never tried".
## Non-goals
- **Anything requiring a view across every repository at once.** This gate sees
@ -167,7 +222,7 @@ without that, a raw scan turns three dead names into about twenty.
npm test
```
135 tests over the pure classifiers. The reference fixtures are measured false
147 tests over the pure classifiers. The reference fixtures are measured false
positives, each with its expected verdict — the six that produced the
three-outcome reference rule, plus the noise sources found by running the gate
against a real repository: regexes inside code spans that are markdown links to

View file

@ -1,6 +1,6 @@
{
"name": "repo-standard",
"version": "0.5.0",
"version": "0.6.0",
"private": true,
"type": "module",
"engines": {

View file

@ -71,7 +71,18 @@
"",
"Consumer-facing documentation is unaffected by working alone, and that is",
"the whole distinction: SECURITY.md, LICENSE, CHANGELOG, non-goals and honest",
"limitations exist for the reader, not for a contributor."
"limitations exist for the reader, not for a contributor.",
"",
"`readme_desc_match: false` turns OFF the README-opening == forge-description",
"equality for a class. Default is on, and it is right for an ordinary repo:",
"both texts describe the SAME subject there. `org-profile` is the one class",
"where they do not — its README is the ORGANISATION's landing page and the",
"forge text describes the REPO. Both are correct about their own subject, so",
"it is the equality that does not apply, not either text. A landing page's",
"opening line also carries a markdown link, and the description field renders",
"as PLAIN TEXT: passing the check would mean putting raw markdown on a real",
"surface — trading a census ERROR for a visible defect. One member, so the",
"exemption removes coverage nowhere else."
],
"classes": {
"plugin": {
@ -92,7 +103,8 @@
"org-profile": {
"required_files": ["README.md"],
"required_headings": [],
"install": "none"
"install": "none",
"readme_desc_match": false
},
"standalone": {
"required_files": ["README.md", "LICENSE"],
@ -101,6 +113,36 @@
}
},
"$comment_titles": [
"Where a decided YES about a README H1 gets written down. A human title is a",
"valid choice — `docs/rds-v1.md` prescribes `1. # Title` for every class, not",
"`# repo-name` — but until this map existed the decision had nowhere to live,",
"so census 05, 06 and 07 would have reported the same 6 WARNs forever.",
"",
"Set: the H1 is compared against it and a match is OK. Unset: WARN, exactly as",
"before. That makes 'we decided this is correct' and 'nobody has looked at it'",
"two different outcomes instead of one.",
"",
"PROPOSED BY THE OPERATOR, NOT MEASURED — like `traits` and `locales`, this is",
"a judgement. The five below are not one phenomenon: `.profile` CANNOT be",
"`# .profile` (the name is Forgejo's mechanism name for the org-profile repo),",
"`llm-ingestion-guard` is not a title at all but the published package name",
"(it is in `non_repos` above for the same reason), and the three plugins are",
"one consistent product convention. Each H1 was read from the repo, not",
"copied from a census.",
"",
"`ai-psychosis` (`# Interaction Awareness`) is DELIBERATELY ABSENT: it is the",
"one where a reader cannot connect the title to the repo. Leaving it standing",
"alone is the wanted effect of registering the others."
],
"titles": {
".profile": "fromaitochitta / open",
"llm-ingestion-pipeline-security": "llm-ingestion-guard",
"linkedin-studio": "LinkedIn Studio Plugin for Claude Code",
"llm-security": "LLM Security Plugin for Claude Code",
"ms-ai-architect": "AI Architect Plugin for Claude Code"
},
"$comment_traits": [
"A SECOND axis, orthogonal to class. Class is structural (read off the",
"catalog and the remotes); a trait is about what the code DOES, which no",

View file

@ -37,6 +37,23 @@ export function readEngineVersion(path = PACKAGE_PATH) {
return JSON.parse(readFileSync(path, 'utf8')).version;
}
// The version names a FILE; only the sha names the CODE. A sweep once stamped
// 18 raw files `0.4.0` while four of them carried findings from a check that
// only exists in 0.5.0 — the feature and the version bump are two commits, so
// the worktree held new code under an old number for a window. Derived from
// this checkout, no network call; null outside a git checkout (a vendored copy
// or a tarball has no HEAD, and that is not a crash).
export function readEngineCommit(dir = join(HERE, '..')) {
try {
return execFileSync('git', ['-C', dir, 'rev-parse', 'HEAD'], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'ignore'],
}).trim() || null;
} catch {
return null;
}
}
const LEVELS = ['OK', 'SKIP', 'WARN', 'ERROR'];
// Findings carry a level AND a bucket, and the two are independent axes.
@ -189,7 +206,7 @@ export function checkDescription(description, register) {
// The opening line makes description == catalog == README: the same thread on a
// third surface, and the only one of the three a machine can check from inside
// the repo.
export function checkFirstScreen({ readme, name, description }) {
export function checkFirstScreen({ readme, name, description, klass }, register) {
const findings = [];
const lines = String(readme ?? '').split('\n');
const firstIdx = lines.findIndex((l) => l.trim() !== '');
@ -211,15 +228,47 @@ export function checkFirstScreen({ readme, name, description }) {
});
return findings;
}
if (heading !== `# ${name}`) {
// A registered title is where that operator call gets WRITTEN DOWN. Without
// one, the same WARN reappears every census and "we decided this is correct"
// is indistinguishable from "nobody has looked". With one, the two separate —
// and a repo whose title nobody has ruled on is left standing alone, which is
// the wanted side effect, not a cost.
const title = register?.titles?.[name];
if (heading === `# ${name}`) {
findings.push({ level: 'OK', code: 'README-H1', msg: `H1 is \`# ${name}\`` });
} else if (title && heading === `# ${title}`) {
findings.push({ level: 'OK', code: 'README-H1', msg: `H1 is \`# ${title}\` — the registered title for \`${name}\`` });
} else if (title) {
findings.push({
level: 'WARN',
code: 'README-H1',
bucket: 'weakening',
msg: `H1 is \`${heading}\`, not \`# ${name}\` — deliberate title, or drift? Operator's call.`,
msg: `H1 is \`${heading}\`, which is neither \`# ${name}\` nor the registered title \`${title}\` — one of the two has drifted.`,
});
} else {
findings.push({ level: 'OK', code: 'README-H1', msg: `H1 is \`# ${name}\`` });
findings.push({
level: 'WARN',
code: 'README-H1',
bucket: 'weakening',
msg: `H1 is \`${heading}\`, not \`# ${name}\` — deliberate title, or drift? Operator's call. Record the decision as \`titles.${name}\` in the register.`,
});
}
// For an ordinary repo the README opening and the forge description describe
// the SAME subject, and equality is the right demand. `org-profile` is the one
// class where they do not: its README is the organisation's landing page and
// the forge text describes the repo. Both are correct about their own subject,
// so it is the EQUALITY that does not apply — and a landing page's opening
// link could only ever match by putting raw markdown on a plain-text surface.
// Class-level data, not a hardcoded name: class rules live in the register.
if (register?.classes?.[klass]?.readme_desc_match === false) {
findings.push({
level: 'OK',
code: 'README-DESC',
msg: `class \`${klass}\` is exempt: the README describes the org, the forge description describes the repo — different subjects, so equality is not required`,
});
return findings;
}
if (description === null || description === undefined) {
@ -883,7 +932,7 @@ export function classifyRepo(
const traits = register.traits?.[name] ?? [];
const readme = (files ?? {})['README.md'] ?? '';
const findings = [
...checkFirstScreen({ readme, name, description }),
...checkFirstScreen({ readme, name, description, klass }, register),
...checkInstallBlock({ readme, name, klass }, register),
...checkInstallTruth({ name, klass, catalogNames }),
...checkHeadings({ readme, klass, traits }, register),
@ -1106,19 +1155,23 @@ const BUCKET_TITLE = {
// engine is visible, not just correctable in hindsight.
const MARK = { OK: '✓', WARN: '!', ERROR: '✗', SKIP: '·' };
export function headerLine(result, engineVersion) {
export function headerLine(result, engineVersion, engineCommit = null) {
const klass = result.klass ? ` [${result.klass}]` : '';
const traits = result.traits?.length ? ` {${result.traits.join(', ')}}` : '';
return `${MARK[result.status]} ${result.name}${klass}${traits}${result.status} (repo-standard v${engineVersion})`;
const sha = engineCommit ? ` @${String(engineCommit).slice(0, 7)}` : '';
return `${MARK[result.status]} ${result.name}${klass}${traits}${result.status} (repo-standard v${engineVersion}${sha})`;
}
export function withEngineVersion(result, engineVersion) {
return { ...result, engineVersion };
// `engineCommit` is always present, null when underivable: an ABSENT key means
// an older engine, an explicit null means this engine ran and had no HEAD to
// read. A consumer sorting raw files by stamp needs those to be different.
export function withEngineVersion(result, engineVersion, engineCommit = null) {
return { ...result, engineVersion, engineCommit };
}
function render(result, engineVersion) {
function render(result, engineVersion, engineCommit) {
const mark = MARK;
console.log(`\n${headerLine(result, engineVersion)}`);
console.log(`\n${headerLine(result, engineVersion, engineCommit)}`);
for (const bucket of BUCKETS) {
const inBucket = result.findings.filter((f) => f.bucket === bucket);
@ -1182,11 +1235,12 @@ async function main(argv) {
const result = inspectRepo(dir, name, register, description, catalogNames);
const engineVersion = readEngineVersion();
const engineCommit = readEngineCommit();
if (argv.includes('--json')) {
console.log(JSON.stringify(withEngineVersion(result, engineVersion), null, 2));
console.log(JSON.stringify(withEngineVersion(result, engineVersion, engineCommit), null, 2));
} else {
render(result, engineVersion);
render(result, engineVersion, engineCommit);
}
process.exit(result.status === 'ERROR' ? 1 : 0);
}

View file

@ -33,6 +33,7 @@ import {
fetchWithRetry,
headerLine,
withEngineVersion,
readEngineCommit,
loadRegister,
} from './repo-standard-check.mjs';
@ -69,9 +70,12 @@ const REGISTER = {
install: 'catalog',
},
'shared-asset': { required_files: ['README.md', 'LICENSE'], required_headings: ['## Non-goals'], install: 'vendor' },
'org-profile': { required_files: ['README.md'], required_headings: [], install: 'none' },
'org-profile': { required_files: ['README.md'], required_headings: [], install: 'none', readme_desc_match: false },
standalone: { required_files: ['README.md', 'LICENSE'], required_headings: ['## Install', '## Non-goals'], install: 'package' },
},
titles: {
'llm-security': 'LLM Security Plugin for Claude Code',
},
traits: {
'llm-security': ['security'],
'llm-ingestion-pipeline-security': ['security'],
@ -306,7 +310,7 @@ test('an unavailable description is SKIP, never a pass', () => {
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.' })
checkFirstScreen({ readme, name: 'repo-mailbox', description: 'A local mailbox for coordination.' }, REGISTER)
.every((f) => f.level === 'OK'),
true,
);
@ -314,17 +318,17 @@ test('README line 1 must be the H1, and the description line must match the forg
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.' });
const f = checkFirstScreen({ readme, name: 'repo-mailbox', description: 'A local mailbox for coordination.' }, REGISTER);
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 });
const f = checkFirstScreen({ readme: '# x\nbody\n', name: 'x', description: null }, REGISTER);
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 });
const f = checkFirstScreen({ readme: 'no heading here\n', name: 'x', description: null }, REGISTER);
assert.equal(f.some((x) => x.level === 'ERROR' && x.code === 'README-H1'), true);
});
@ -332,16 +336,84 @@ 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 });
const f = checkFirstScreen({ readme: '# OKR for Public Sector\nbody\n', name: 'okr', description: null }, REGISTER);
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' });
const f = checkFirstScreen({ readme: '# Nice Title\nthe description\n', name: 'x', description: 'the description' }, REGISTER);
assert.equal(f.some((x) => x.code === 'README-DESC' && x.level === 'OK'), true);
});
// ------------------------------------------------- registered README titles
// Census 05 measured the same 6 README-H1 WARNs three rounds running, because
// a decided YES had nowhere to live. `titles` is that place: with an entry the
// H1 is OK, without one it WARNs exactly as before — so "we decided this" and
// "nobody has looked at it" stop sharing one outcome. The wanted side effect is
// that a repo nobody has ruled on stands alone once the others are registered.
test('an H1 matching the registered title is OK, not a WARN', () => {
const readme = '# LLM Security Plugin for Claude Code\nbody\n';
const f = checkFirstScreen({ readme, name: 'llm-security', description: null }, REGISTER);
assert.equal(f.some((x) => x.code === 'README-H1' && x.level === 'OK'), true);
assert.equal(f.some((x) => x.code === 'README-H1' && x.level === 'WARN'), false);
});
test('a repo with no registered title still WARNs — deciding and not looking stay different outcomes', () => {
const f = checkFirstScreen({ readme: '# Interaction Awareness\nbody\n', name: 'repo-mailbox', description: null }, REGISTER);
assert.equal(f.some((x) => x.code === 'README-H1' && x.level === 'WARN'), true);
});
test('an H1 matching neither the name nor the registered title WARNs, and the message names both', () => {
const f = checkFirstScreen({ readme: '# Something Drifted\nbody\n', name: 'llm-security', description: null }, REGISTER);
const warn = f.find((x) => x.code === 'README-H1' && x.level === 'WARN');
assert.ok(warn, 'expected a README-H1 WARN');
assert.match(warn.msg, /Something Drifted/);
assert.match(warn.msg, /LLM Security Plugin for Claude Code/);
});
test('the repo name still passes when a title is registered — both spellings are accepted', () => {
const f = checkFirstScreen({ readme: '# llm-security\nbody\n', name: 'llm-security', description: null }, REGISTER);
assert.equal(f.some((x) => x.code === 'README-H1' && x.level === 'OK'), true);
});
// --------------------------------------------- org-profile README-DESC exemption
// For an ordinary repo the README opening and the forge description describe the
// SAME subject, and equality is the right demand. For `org-profile` they do not:
// the README is the organisation's landing page, the forge description describes
// the repo. Both texts are correct about their own subject. The description field
// also renders as PLAIN TEXT, so a landing page's opening link could only ever
// match by putting raw markdown on a real surface.
const PROFILE_README = '# .profile\nCompanion repos, plugins, and tools for [From AI to Chitta](https://fromaitochitta.com).\n';
test('org-profile is exempt from the README-DESC equality check', () => {
const f = checkFirstScreen(
{ readme: PROFILE_README, name: '.profile', klass: 'org-profile', description: 'Organization profile and navigation for the open org.' },
REGISTER,
);
const desc = f.find((x) => x.code === 'README-DESC');
assert.ok(desc, 'expected a README-DESC finding — an exemption must still be recorded');
assert.equal(desc.level, 'OK');
assert.equal(f.some((x) => x.level === 'ERROR'), false);
});
test('the exemption is per class, not global — the same README under a plugin class is still an ERROR', () => {
const f = checkFirstScreen(
{ readme: PROFILE_README, name: 'llm-security', klass: 'plugin', description: 'Organization profile and navigation for the open org.' },
REGISTER,
);
assert.equal(f.some((x) => x.code === 'README-DESC' && x.level === 'ERROR'), true);
});
test('the exemption does not silence the H1 check for org-profile', () => {
const f = checkFirstScreen(
{ readme: 'no heading here\n', name: '.profile', klass: 'org-profile', description: 'anything' },
REGISTER,
);
assert.equal(f.some((x) => x.code === 'README-H1' && x.level === 'ERROR'), true);
});
// ------------------------------------------------------------ install block
const MKT = REGISTER.marketplace;
@ -1390,3 +1462,44 @@ test('withEngineVersion adds the version without disturbing existing fields', ()
assert.equal(stamped.status, 'OK');
assert.deepEqual(result, { name: 'x', klass: 'plugin', status: 'OK', findings: [] });
});
// ---------------------------------------------------- engine commit stamp
// Measured 2026-08-09 by org-ops: a sweep stamped 18 raw files `0.4.0`, and
// four of them carried findings from a check that only exists in 0.5.0. The
// stamp lied without being broken — `9eb210b` (the feature) and `63c75d8` (the
// version bump) are TWO commits, so the worktree held new code under an old
// number for a window. The version names a FILE; only the sha names the CODE,
// and the bump is by definition a different commit from the change it describes.
test('headerLine names the engine commit alongside the version', () => {
const line = headerLine({ name: 'voyage', klass: 'plugin', traits: [], status: 'OK' }, '0.5.0', 'a7276e6f0d1e2b3c');
assert.match(line, /0\.5\.0/);
assert.match(line, /a7276e6/);
});
test('headerLine falls back to the version alone when the commit is underivable', () => {
const line = headerLine({ name: 'voyage', klass: 'plugin', traits: [], status: 'OK' }, '0.5.0', null);
assert.match(line, /0\.5\.0/);
assert.doesNotMatch(line, /null|undefined/);
});
test('withEngineVersion stamps the commit next to the version', () => {
const stamped = withEngineVersion({ name: 'x', status: 'OK', findings: [] }, '0.5.0', 'a7276e6f0d1e2b3c');
assert.equal(stamped.engineVersion, '0.5.0');
assert.equal(stamped.engineCommit, 'a7276e6f0d1e2b3c');
});
test('engineCommit is present-and-null when underivable, never absent', () => {
// An ABSENT key means an older engine; an explicit null means this engine ran
// and could not derive the sha. A consumer sorting raw files by stamp needs
// those two to be different, which is the whole point of the field.
const stamped = withEngineVersion({ name: 'x', status: 'OK', findings: [] }, '0.5.0', null);
assert.equal(Object.hasOwn(stamped, 'engineCommit'), true);
assert.equal(stamped.engineCommit, null);
});
test('readEngineCommit returns null outside a git checkout instead of throwing', () => {
// Derived from the engine's own checkout with no network call. A consumer of
// a tarball or a vendored copy has no HEAD, and that is not a crash.
assert.equal(readEngineCommit('/nonexistent-path-for-repo-standard-test'), null);
});