Article rule 1 ("give Claude judgement instead of rules") gets its register
entry, and deliberately no detector. `BP-JUDG-001` carries `lensCheck: null`.
The cut between deterministic prefilter and prose judge was the open design
decision. It was settled by measurement, and the measurement declined both
halves:
- 409 real CLAUDE.md files (38488 lines, 8689 prose blocks): the caging class
fires 7 times, and all 7 are false positives ("rendered prose-side",
"naming is a flag on the class"). Verified along an independent grep path
that bypasses block-splitting and sentence-splitting entirely, in both word
orders: 5 lines and 1 line, none an instruction.
- The narrow variant (absolute + form noun + numeric cap) fired 8 times —
one duplicated block seen seven times across plugin caches, precision 0 %.
The pre-committed rule required 90 % over 20 distinct fires.
- Where the shape does occur — 45 lines across 4755 skill/agent/command files
— it is the author's editorial policy (emoji, sentence length, slide
titles). Nothing in the text separates that from a vendor's over-tight
guardrail, and the article's reasoning does not transfer: the model is not
the author of a user's config.
So no CA-OPT-002; finding-codes keeps OPT next-free = 2. The numbers live in
the entry's own `note`, so the next session does not re-derive the question.
Two premises the chunk falsified. The brief justified a separate axis by
saying these blocks sit inside `floor-exclusion`'s floor — but the article's
own canonical line carries no floor marker at all, so "inside the floor"
cannot define the axis (the corpus tendency is 76 %, which is a tendency, not
a mechanism). And the fasit's own form-noun vocabulary was wrong: `name` and
`format` alone drove 97 % of fires.
Not folded into `--subtract`: a third "loosen instead of delete" verdict in
the subtraction judge is the AS#5 mixing STATE forbids, and with the corrected
vocabulary there are 0 collisions to arbitrate anyway.
Guards, both seen red against their own defect first: the entry must exist,
be confirmed, date its source and name NO lensCheck; and every lensCheck in
the register must be backed by a real detector.
No behaviour changed — no new finding, no output change, nothing consumes the
entry yet — hence `docs`, not `feat`. Suite 1701 -> 1703/0; frozen v5.0.0 and
default-output baselines 0 changed files. Fasit:
docs/b2-judgment-lens-fasit.local.md
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017mCkx9wGywqNQzsXkBMzJ1
242 lines
8.7 KiB
JavaScript
242 lines
8.7 KiB
JavaScript
import { describe, it } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {
|
|
loadRegister,
|
|
validateRegister,
|
|
getEntry,
|
|
CONFIDENCE_LEVELS,
|
|
REGISTER_PATH,
|
|
} from '../../scanners/lib/best-practices-register.mjs';
|
|
import { LENS_DETECTORS } from '../../scanners/lib/lens-prefilter.mjs';
|
|
import { SUBTRACT_DETECTORS } from '../../scanners/lib/subtraction-prefilter.mjs';
|
|
|
|
// A minimal well-formed entry; negative tests clone + mutate this.
|
|
const validEntry = () => ({
|
|
id: 'BP-TEST-001',
|
|
claim: 'A representative best-practice claim.',
|
|
confidence: 'confirmed',
|
|
source: { url: 'https://example.com/doc', title: 'Doc', verified: '2026-06-20' },
|
|
});
|
|
|
|
const wrap = (entries) => ({ version: 1, entries });
|
|
|
|
describe('CONFIDENCE_LEVELS', () => {
|
|
it('has the three documented levels', () => {
|
|
assert.deepStrictEqual([...CONFIDENCE_LEVELS].sort(), ['confirmed', 'inferred', 'unverified']);
|
|
});
|
|
it('is frozen', () => {
|
|
assert.throws(() => { CONFIDENCE_LEVELS.push('x'); }, TypeError);
|
|
});
|
|
});
|
|
|
|
describe('loadRegister (bundled register)', () => {
|
|
it('loads the bundled register file', () => {
|
|
const reg = loadRegister();
|
|
assert.equal(typeof reg, 'object');
|
|
assert.equal(reg.version, 1);
|
|
assert.ok(Array.isArray(reg.entries));
|
|
assert.ok(reg.entries.length > 0, 'register should ship with seed entries');
|
|
});
|
|
|
|
it('REGISTER_PATH points at knowledge/best-practices.json', () => {
|
|
assert.match(String(REGISTER_PATH), /knowledge\/best-practices\.json$/);
|
|
});
|
|
});
|
|
|
|
describe('bundled register integrity (Verifiseringsplikt)', () => {
|
|
const reg = loadRegister();
|
|
|
|
it('passes schema validation with zero errors', () => {
|
|
const result = validateRegister(reg);
|
|
assert.deepStrictEqual(result.errors, []);
|
|
assert.equal(result.valid, true);
|
|
});
|
|
|
|
it('has unique ids', () => {
|
|
const ids = reg.entries.map((e) => e.id);
|
|
assert.equal(new Set(ids).size, ids.length);
|
|
});
|
|
|
|
it('uses the BP-TOPIC-NNN id convention', () => {
|
|
for (const e of reg.entries) {
|
|
assert.match(e.id, /^BP-[A-Z]+-\d{3}$/, `bad id: ${e.id}`);
|
|
}
|
|
});
|
|
|
|
it('seeds only CONFIRMED claims (no unverified assertion enters the consumed register)', () => {
|
|
for (const e of reg.entries) {
|
|
assert.equal(e.confidence, 'confirmed', `${e.id} must be confirmed in the seed`);
|
|
}
|
|
});
|
|
|
|
it('every entry carries a source url + verified date', () => {
|
|
for (const e of reg.entries) {
|
|
assert.ok(e.source && e.source.url, `${e.id} missing source.url`);
|
|
assert.match(e.source.verified, /^\d{4}-\d{2}-\d{2}$/, `${e.id} bad verified date`);
|
|
}
|
|
});
|
|
|
|
// A corroborating source without a published date is a SILENT hole: newestEvidenceMs()
|
|
// returns null for the entry and the evidence-age rule cannot judge evidence it cannot
|
|
// date, so the entry stays green on evidence of any age. Assert the blanket invariant,
|
|
// not the entries that happen to have one today.
|
|
it('every corroborating source carries a published date (evidence-age rule has teeth)', () => {
|
|
for (const e of reg.entries) {
|
|
if (!Array.isArray(e.sources)) continue;
|
|
e.sources.forEach((s, i) => {
|
|
assert.match(
|
|
String(s && s.published),
|
|
/^\d{4}-\d{2}-\d{2}$/,
|
|
`${e.id} sources[${i}] (${s && s.url}) missing a parseable published date`
|
|
);
|
|
});
|
|
}
|
|
});
|
|
|
|
it('carries the model-routing entries (C1), each dated by a published source', () => {
|
|
for (const id of ['BP-MODEL-001', 'BP-MODEL-002']) {
|
|
const e = getEntry(reg, id);
|
|
assert.ok(e, `${id} missing from the bundled register`);
|
|
assert.equal(e.confidence, 'confirmed', `${id} must be confirmed`);
|
|
assert.equal(e.category, 'model-fit', `${id} wrong category`);
|
|
assert.ok(
|
|
e.source.url.startsWith('https://code.claude.com/docs/'),
|
|
`${id} primary source must be the official docs, got ${e.source.url}`
|
|
);
|
|
assert.ok(
|
|
Array.isArray(e.sources) && e.sources.some((s) => s.published),
|
|
`${id} must carry a corroborating source with a published date (B1 evidence-age rule)`
|
|
);
|
|
}
|
|
});
|
|
|
|
// B2. The judgment entry is knowledge WITHOUT a detector, and that is the
|
|
// measured outcome, not an omission: the caging class the article names fired
|
|
// 7 times across 409 real CLAUDE.md files and all 7 were false positives
|
|
// (docs/b2-judgment-lens-fasit.local.md §9.4). Asserting the absent lensCheck
|
|
// is what stops a later session from "completing" the entry by wiring a
|
|
// detector the corpus refused.
|
|
it('carries the judgment entry (B2) as detector-less knowledge', () => {
|
|
const e = getEntry(reg, 'BP-JUDG-001');
|
|
assert.ok(e, 'BP-JUDG-001 missing from the bundled register');
|
|
assert.equal(e.confidence, 'confirmed', 'BP-JUDG-001 must be confirmed');
|
|
assert.equal(e.category, 'judgment-fit', 'BP-JUDG-001 wrong category');
|
|
assert.equal(
|
|
e.lensCheck ?? null,
|
|
null,
|
|
'BP-JUDG-001 must NOT name a lensCheck — no detector survived measurement'
|
|
);
|
|
assert.equal(
|
|
e.source.url,
|
|
'https://claude.com/blog/the-new-rules-of-context-engineering-for-claude-5-generation-models',
|
|
'BP-JUDG-001 primary source must be the article that states rule 1'
|
|
);
|
|
assert.equal(e.source.published, '2026-07-24', 'BP-JUDG-001 must date its primary source');
|
|
assert.match(
|
|
String(e.note),
|
|
/409/,
|
|
'BP-JUDG-001 must carry the measured negative result, so it is not re-derived'
|
|
);
|
|
});
|
|
|
|
// The register's own consumers key on lensCheck; an entry that names one it
|
|
// does not have would reach a payload with no detector behind it.
|
|
it('every lensCheck in the register is backed by a detector', () => {
|
|
const detectors = new Set([
|
|
...LENS_DETECTORS.map((d) => d.lensCheck),
|
|
...SUBTRACT_DETECTORS.map((d) => d.lensCheck),
|
|
// Scanner-side checks that are their own detector.
|
|
'procedure-in-claude-md',
|
|
'CA-OST-001',
|
|
'CA-CML-001',
|
|
'CA-SKL-002',
|
|
]);
|
|
for (const e of reg.entries) {
|
|
if (e.lensCheck == null) continue;
|
|
assert.ok(
|
|
detectors.has(e.lensCheck),
|
|
`${e.id} names lensCheck "${e.lensCheck}" with no detector behind it`
|
|
);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('validateRegister (negative cases)', () => {
|
|
it('accepts a minimal valid register', () => {
|
|
assert.equal(validateRegister(wrap([validEntry()])).valid, true);
|
|
});
|
|
|
|
it('rejects a non-object', () => {
|
|
assert.equal(validateRegister(null).valid, false);
|
|
assert.equal(validateRegister('nope').valid, false);
|
|
});
|
|
|
|
it('rejects a non-numeric version', () => {
|
|
const r = validateRegister({ version: 'one', entries: [validEntry()] });
|
|
assert.equal(r.valid, false);
|
|
assert.ok(r.errors.some((m) => /version/.test(m)));
|
|
});
|
|
|
|
it('rejects non-array entries', () => {
|
|
const r = validateRegister({ version: 1, entries: {} });
|
|
assert.equal(r.valid, false);
|
|
assert.ok(r.errors.some((m) => /entries/.test(m)));
|
|
});
|
|
|
|
it('rejects duplicate ids', () => {
|
|
const r = validateRegister(wrap([validEntry(), validEntry()]));
|
|
assert.equal(r.valid, false);
|
|
assert.ok(r.errors.some((m) => /duplicate/i.test(m)));
|
|
});
|
|
|
|
it('rejects a missing claim', () => {
|
|
const e = validEntry(); delete e.claim;
|
|
const r = validateRegister(wrap([e]));
|
|
assert.equal(r.valid, false);
|
|
assert.ok(r.errors.some((m) => /claim/.test(m)));
|
|
});
|
|
|
|
it('rejects an out-of-enum confidence', () => {
|
|
const e = validEntry(); e.confidence = 'maybe';
|
|
const r = validateRegister(wrap([e]));
|
|
assert.equal(r.valid, false);
|
|
assert.ok(r.errors.some((m) => /confidence/.test(m)));
|
|
});
|
|
|
|
it('rejects a malformed verified date', () => {
|
|
const e = validEntry(); e.source.verified = '20-06-2026';
|
|
const r = validateRegister(wrap([e]));
|
|
assert.equal(r.valid, false);
|
|
assert.ok(r.errors.some((m) => /verified|date/i.test(m)));
|
|
});
|
|
|
|
it('rejects a missing source url', () => {
|
|
const e = validEntry(); delete e.source.url;
|
|
const r = validateRegister(wrap([e]));
|
|
assert.equal(r.valid, false);
|
|
assert.ok(r.errors.some((m) => /source|url/i.test(m)));
|
|
});
|
|
|
|
it('rejects an out-of-enum severity when present', () => {
|
|
const e = validEntry(); e.severity = 'urgent';
|
|
const r = validateRegister(wrap([e]));
|
|
assert.equal(r.valid, false);
|
|
assert.ok(r.errors.some((m) => /severity/.test(m)));
|
|
});
|
|
|
|
it('accepts a valid optional severity', () => {
|
|
const e = validEntry(); e.severity = 'low';
|
|
assert.equal(validateRegister(wrap([e])).valid, true);
|
|
});
|
|
});
|
|
|
|
describe('getEntry', () => {
|
|
const reg = loadRegister();
|
|
it('returns the entry for a known id', () => {
|
|
const first = reg.entries[0];
|
|
assert.equal(getEntry(reg, first.id), first);
|
|
});
|
|
it('returns undefined for an unknown id', () => {
|
|
assert.equal(getEntry(reg, 'BP-NOPE-999'), undefined);
|
|
});
|
|
});
|