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

@ -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);
}