#!/usr/bin/env node
/**
* `npm run check:claims` — a mechanical gate on the SHIPPED OUTPUT.
*
* Pouya's ruling, 2026-08-29, and the reasoning is the point:
*
* "Your recurring failure this project is a specific shape: you write a rule
* into a header comment, then breach it in the file below, in the same
* change set. Q53's sweep, Q54's gate four times, the D13 'cannot' phrasing
* fifty lines under your own warning about it. That is not a discipline
* problem — prose in a comment does not govern the writing that follows it.
* The pattern that actually worked was mechanical: deleting the `class` prop
* so passing one is a build error. Nobody has breached that since."
*
* So this is not documentation. It is a build error.
*
* SCOPE — `dist/**\/*.html` AND NOTHING ELSE. Not `AGENTS.md`, not `docs/`, not
* `src/`. D19 bounds review to what ships, and §4's Forbidden table says in as
* many words that it "governs published pages… It is not a word filter over the
* repository's own documentation." A register that records a forbidden phrase in
* order to forbid it must not be failed by its own quotation of it.
*
* `',
'Software contracts, SLA and MSA breakdowns, data residency and processing, AI vendor diligence, IP and licensing.',
/* The approved replacements for the two negatives struck on 2026-08-29,
which were 'The Q.Arb pathway commenced in August 2026; C.Med-Arb is
the endpoint.' and a bare 'Chartered Med-Arbitrator'. Both are now
breaches, and both moved to mustMatch. */
'Q.Med (ADRIC / ADRIO) · Q.Arb (ADRIC / ADRIO)',
/* The expansion in approved use — §11 definitional, no stage word. */
'Q.Arb stands for Qualified Arbitrator, an ADRIC and ADRIO designation.',
/* `once` and `when` were BARE stage words for one run, and all four of these
compliant sentences failed the build. They now require a hold-verb. */
'I hold Q.Med and Q.Arb, and I say so when a party asks',
'Q.Arb (ADRIC / ADRIO), which is what parties look at when they appoint',
'Once appointed, I hold Q.Arb and act as sole arbitrator',
'Q.Arb, and when the parties agree the process runs on that basis',
/* `hold` is a common verb on an arbitration page with a different object;
the repair narrowed `once|when` rather than closing it, and this shipped
past it for one run. The hold-verb must now take the designation. */
'I hold Q.Arb, and when I hold a preliminary conference the parties attend',
'I hold the Q.Med and Q.Arb designations through the ADR Institute of Canada and the ADR Institute of Ontario.',
/* The false positive the first form of `c-med-arb-struck` produced. */
'The ADR Institute of Canada publishes ADRIC Med-Arb Rules, developed by a task force.',
'The ADRIC National Mediation Rules.',
'adopted a new edition effective 1 March 2025',
'Commercial arbitration in Ontario. I do not accept family arbitration.',
'Published as typical, not as a guarantee.',
'Liens, delay and change-order claims, scheduling, subcontract and deficiency disputes.',
],
};
/* --- machinery ----------------------------------------------------------- */
/* `relative()` escapes the root with `../../..` when the optional path argument
points outside the repo (which only a test run does). Show the plain absolute
path in that case — an unreadable path in a failure report is one more thing
between a reader and the match. */
function rel(p) {
const r = relative(ROOT, p);
return r && !r.startsWith('..') ? r : p;
}
function walk(dir) {
const out = [];
for (const entry of readdirSync(dir, { withFileTypes: true })) {
const full = join(dir, entry.name);
if (entry.isDirectory()) out.push(...walk(full));
else if (entry.name.endsWith('.html')) out.push(full);
}
return out;
}
function newestMtime(paths) {
let newest = 0;
let which = null;
const visit = (p) => {
const s = statSync(p);
if (s.isDirectory()) {
for (const e of readdirSync(p)) visit(join(p, e));
} else if (s.mtimeMs > newest) {
newest = s.mtimeMs;
which = p;
}
};
for (const p of paths) visit(p);
return { newest, which };
}
/**
* Strip what is not published prose or published data.
*
* `