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:
parent
a7276e6f78
commit
5884a64e54
8 changed files with 358 additions and 27 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue