feat: Q.Arb is held; strike C.Med-Arb entirely; dissolve the paired disclosure
Build and deploy / build-and-deploy (push) Failing after 4s
Build and deploy / build-and-deploy (push) Failing after 4s
Pouya's ruling, 2026-08-29. Treated as D3-class and swept accordingly. §4 Q.Arb becomes a HELD designation. Obtained July 2026 — recorded in the register, deliberately not published. Public copy carries "Q.Arb (ADRIC / ADRIO)" beside Q.Med and nothing more. Every stage form is struck: "commenced", "in progress", "pathway", "not yet". C.Med-Arb as a stated goal is struck. This DEVIATES FROM THE STRATEGY BRIEF, which made it "the explicit long-term professional narrative"; the brief is not in this repository, so the deviation is recorded in four places so nobody reinstates it from a document no reader can open. The designation stays in §11 as a definition — what is struck is its status as a goal of his. The paired-disclosure condition dissolves. It existed only because Q.Arb was in progress; there is no stage left to disclose, and a condition with no subject cannot be half-kept. Pages /about/'s credentialing arc is DELETED, not rewritten — two held designations are not a journey. /arbitration/ loses its stage section and its "Available now, and open about the stage" h1. /med-arb/'s endpoint section is rewritten. Deleting CREDENTIALS.goal/goalName rather than emptying them turned every consumer into a build error, which is how the last two surfaced. hasCredential now maps CREDENTIALS.designations instead of indexing [0]; _DesignationRowParity pins the visible credential row to the same constant. check:claims q-arb-as-a-stage (inverted from the predecessor, which barred Q.Arb reading as HELD) and c-med-arb-struck. Each page is now scanned twice — as published, and with inline tags collapsed — because [^<] cannot cross <strong>, which this site sets in prose. Two open questions for Pouya, neither blocking: Q55 — the acquisition date. §4 says obtained July 2026; the Change Log of 2026-08-26 records "commenced August 2026", both stamped [verified — Pouya]. They cannot both be true. Nothing published turns on it. Q56 — is the mediation offering scoped commercial? §4 leaves it unscoped; four surfaces say "commercial mediation"; /practice/insurance/ offers mediation in insured-versus-insurer SABS matters. Two review rounds, all findings applied or declined with a stated reason. Round 2 found ten lines in docs/03 still instructing the struck form — the 2026-08-29 sweep missed them because `git grep 'Q.Arb'` is line-anchored and the block never names it. Sweep the vocabulary, not only the subject. Gates, exit statuses read directly, never through a pipe: npm run check exit=0 (0 errors, 0 warnings, 0 hints) npm run lint exit=0 npm run build exit=0 (12 pages) npm run check:claims exit=0 (11 patterns, 26 approved strings) npm audit exit=0 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
co-authored by
Claude Opus 5
parent
79b19a7bd0
commit
610edc24fd
+206
-23
@@ -177,14 +177,72 @@ const PATTERNS = [
|
||||
re: /\bS\.?\s?M\.?\s+Lawrence\b|\b07452218\b/gi,
|
||||
},
|
||||
{
|
||||
id: 'q-arb-as-held',
|
||||
rule: '§4 Forbidden — Q.Arb must never read as held, imminent, or nearly complete.',
|
||||
id: 'q-arb-as-a-stage',
|
||||
rule: '§4 — Q.Arb is HELD. It must never read as a stage, a pathway, or pending.',
|
||||
incident:
|
||||
'It commenced August 2026. The recurring drift is one word: docs/03 said ' +
|
||||
'the Q.Arb "designation commenced in August 2026" — which reads as in ' +
|
||||
'force since then, i.e. HELD — in copy an implementer is told to lift ' +
|
||||
'verbatim. Found by claims-auditor 2026-08-28. §4 requires "pathway".',
|
||||
re: /Q\.?\s?Arb\s+designation\b|\b(holds?|holding|awarded|conferred|earned|achieved)\s+(the\s+|a\s+)?Q\.?\s?Arb\b|Q\.?\s?Arb[^.<]{0,60}\b(nearly|almost) complete\b|Q\.?\s?Arb[^.<]{0,60}\bin progress\b/gi,
|
||||
'THIS PATTERN WAS INVERTED ON 2026-08-29 AND ITS PREDECESSOR IS GONE. It ' +
|
||||
'used to bar Q.Arb reading as HELD, because §4 recorded it as "commenced ' +
|
||||
'August 2026"; Pouya ruled it held (obtained July 2026, date NOT ' +
|
||||
'published), so every stage word now understates a real credential. The ' +
|
||||
'site carried the struck forms on six surfaces — an h1 reading "Available ' +
|
||||
'now, and open about the stage", a whole /arbitration/ section headed ' +
|
||||
'"Where I am in the arc", /about/\'s arc section, the footer strip, and ' +
|
||||
'both JSON-LD nodes. Publish "Q.Arb (ADRIC / ADRIO)" and nothing more.',
|
||||
/* ~50 characters either side, per Pouya's specification. The window stops at
|
||||
the next TAG boundary so it cannot leap a paragraph. It stopped at a
|
||||
sentence boundary too (`[^.<]`) until the fixture below proved that too
|
||||
tight: "Qualified Arbitrator. Newly commenced" splits the anchor from the
|
||||
stage word across a full stop, 22 characters apart, and that is precisely
|
||||
the copy this pattern exists for. The self-test caught the regression.
|
||||
|
||||
⚠️ THE ANCHOR MATCHES THE EXPANSION TOO, and it did not on the first
|
||||
draft. Tested against the nine strings this change set removed: it caught
|
||||
seven and MISSED "Qualified Arbitrator. Newly commenced — not held, and
|
||||
not nearing completion." — /about/'s own arc body, which never wrote the
|
||||
abbreviation. An abbreviation-only anchor cannot see copy that spells the
|
||||
designation out, and prose is exactly where it gets spelled out.
|
||||
|
||||
KNOWN LIMIT, stated rather than papered over: this cannot catch a stage
|
||||
expressed without naming the designation at all. The h1 it replaced —
|
||||
"Available now, and open about the stage" — matches nothing here and no
|
||||
regex over shipped HTML would catch it without firing on ordinary copy.
|
||||
That one is `claims-auditor`'s. */
|
||||
/* WHAT EACH ALTERNATIVE IS FOR, because none is obvious from the regex:
|
||||
(1) stage word after the designation, (2) before it, (3) an acquisition
|
||||
DATE near it — §4 records July 2026 and bars publishing it, and docs/03
|
||||
cited this script as enforcing that before it did (the Q22 shape) —
|
||||
(4) "once/when I hold it", which must take the designation as its object
|
||||
or it fires on "when I hold a preliminary conference".
|
||||
|
||||
THE ANCHOR MATCHES THE EXPANSION because `docs/03` authorises "Qualified
|
||||
Arbitrator" as publishable prose, and prose is where it gets spelled out.
|
||||
|
||||
KNOWN LIMIT, stated rather than papered over: this cannot catch a stage
|
||||
expressed without naming the designation. The h1 it replaced — "Available
|
||||
now, and open about the stage" — matches nothing here, and no regex over
|
||||
shipped HTML would catch it without firing on ordinary copy. That one is
|
||||
`claims-auditor`'s. */
|
||||
re: /(?:Q\.?\s?Arb|Qualified Arbitrator)\b[^<\uE000]{0,50}?\b(commenc\w*|in progress|pathway|not yet|not held|nearing completion|pending|working toward|under ?way)\b|\b(commenc\w*|in progress|pathway|not yet|not held|nearing completion|pending|working toward|under ?way)\b[^<\uE000]{0,50}?\b(?:Q\.?\s?Arb|Qualified Arbitrator)\b|(?:Q\.?\s?Arb|Qualified Arbitrator)\b[^<\uE000]{0,50}?\b(?:January|February|March|April|May|June|July|August|September|October|November|December)\s+20\d\d\b|\b(?:January|February|March|April|May|June|July|August|September|October|November|December)\s+20\d\d\b[^<\uE000]{0,50}?\b(?:Q\.?\s?Arb|Qualified Arbitrator)\b|\b(?:once|when)\s+(?:I|he)\s+(?:holds?|obtains?|receives?|completes?)\s+(?:it\b|the\s+)?(?:Q\.?\s?Arb|designation)\b/gi,
|
||||
},
|
||||
{
|
||||
id: 'c-med-arb-struck',
|
||||
rule: 'C.Med-Arb is out entirely — it appears on no page (Pouya, 2026-08-29).',
|
||||
incident:
|
||||
'It was the strategy brief\'s "explicit long-term professional narrative" ' +
|
||||
'and it shipped on /, /about/, /arbitration/ and /med-arb/ as the endpoint ' +
|
||||
'of a credentialing arc. Pouya dispensed with it: he holds Q.Med and ' +
|
||||
'Q.Arb, which is what med-arb requires. THE DESIGNATION IS STILL REAL and ' +
|
||||
'stays in AGENTS.md §11 as a definition — this bars naming it in shipped ' +
|
||||
'output, not knowing what it is. Barred in every spelling both ' +
|
||||
'institutions use, because the reinstatement risk is a well-meaning ' +
|
||||
'implementer reading the brief, not a typo.',
|
||||
/* ⚠️ THE LEADING \b AND THE MANDATORY DOT ARE BOTH LOAD-BEARING, and this
|
||||
pattern shipped without them for one run. `C\.?\s?Med-Arb` matched
|
||||
"ADRIC Med-Arb Rules" as "C Med-Arb" — the C of ADRIC, a space, then the
|
||||
real rule-set name — and failed the build on approved copy on /med-arb/.
|
||||
The abbreviation always carries the dot; "C Med-Arb" is not a form either
|
||||
institution uses. The fixture below pins it. */
|
||||
re: /\bC\.\s?Med-Arb(?:itrat(?:or|ion))?s?\b|\bChartered Med-Arb(?:itrat(?:or|ion))?s?\b/gi,
|
||||
},
|
||||
{
|
||||
id: 'struck-universal-q39',
|
||||
@@ -252,11 +310,36 @@ const FIXTURES = {
|
||||
'the best mediator',
|
||||
],
|
||||
'fabricated-founder': ['S. M. Lawrence', 'Co. № 07452218'],
|
||||
'q-arb-as-held': [
|
||||
'the Q.Arb designation',
|
||||
'holds Q.Arb',
|
||||
'Q.Arb is nearly complete',
|
||||
'Q.Arb, in progress',
|
||||
'q-arb-as-a-stage': [
|
||||
'The Q.Arb pathway commenced in August 2026',
|
||||
'Q.Arb is in progress',
|
||||
'Q.Arb — not yet held',
|
||||
'once I hold Q.Arb',
|
||||
'my Q.Arb pathway',
|
||||
/* The expansion, which the first draft of this pattern missed. */
|
||||
'Qualified Arbitrator. Newly commenced — not held, and not nearing completion.',
|
||||
/* The acquisition date, which no stage word caught. */
|
||||
'Q.Arb, obtained July 2026',
|
||||
'Q.Arb (ADRIC / ADRIO), held since July 2026',
|
||||
/* The `rule` line above named these and the regex never matched them —
|
||||
a documented control not covering what it is cited for (Q22's shape). */
|
||||
'Q.Arb is pending',
|
||||
'Q.Arb — the designation I am working toward',
|
||||
'the Q.Arb process is under way',
|
||||
],
|
||||
'c-med-arb-struck': [
|
||||
'C.Med-Arb is the endpoint',
|
||||
'Chartered Med-Arbitrator',
|
||||
'the ADRIC Chartered Med-Arb designation',
|
||||
/* The blend §11's own expansion invites, which the trailing \b in the
|
||||
first draft made invisible: `C\.Med-Arb\b` cannot match when the next
|
||||
character is a word char. */
|
||||
'the C.Med-Arbitrator designation',
|
||||
'Chartered Med-Arbitration',
|
||||
/* Plurals: the trailing \b survived the first repair and blocked these. */
|
||||
'Chartered Med-Arbitrators',
|
||||
'C.Med-Arbitrators',
|
||||
'C.Med-Arbitration',
|
||||
],
|
||||
'struck-universal-q39': [
|
||||
'Anyone may be appointed an arbitrator in Ontario',
|
||||
@@ -286,8 +369,26 @@ const FIXTURES = {
|
||||
inside <style>. */
|
||||
'<style>.hero-lede{line-height:var(--leading-body);color:var(--text-secondary)}</style>',
|
||||
'Software contracts, SLA and MSA breakdowns, data residency and processing, AI vendor diligence, IP and licensing.',
|
||||
'The Q.Arb pathway commenced in August 2026; C.Med-Arb is the endpoint.',
|
||||
'Chartered Med-Arbitrator',
|
||||
/* 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.',
|
||||
@@ -364,6 +465,53 @@ function publishedText(html) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* THE SECOND VIEW, AND IT EXISTS BECAUSE `<strong>` DEFEATED THE GATE.
|
||||
*
|
||||
* `publishedText` leaves tags in place, and several patterns use `[^<]` as a
|
||||
* window boundary so they cannot leap a paragraph. That boundary also stops
|
||||
* them crossing INLINE markup: `<strong>Q.Arb</strong> — the pathway commenced
|
||||
* in August 2026` matched nothing, and this site sets `<strong>` in prose on
|
||||
* `/arbitration/` and `/`. Found by `adversarial-reviewer` 2026-08-30.
|
||||
*
|
||||
* So every page is scanned TWICE — once as published, once with inline tags
|
||||
* collapsed to a single space. Block-level tags collapse to a full stop
|
||||
* instead, which preserves the "do not leap a paragraph" property that made the
|
||||
* `[^.<]` window worth having in the first place. Matches are deduplicated by
|
||||
* the matched text, so a hit visible in both views is reported once.
|
||||
*/
|
||||
const BLOCK_TAGS =
|
||||
/<\/?(?:p|div|section|article|header|footer|nav|main|aside|h[1-6]|li|ul|ol|dl|dt|dd|table|tr|td|th|blockquote|figure|figcaption|br|hr)\b[^>]*>/gi;
|
||||
|
||||
/**
|
||||
* ⚠️ THE BLOCK BOUNDARY IS A SENTINEL (`\uE000`), NOT A FULL STOP, AND THAT IS
|
||||
* WHAT LETS ONE REGEX SERVE BOTH VIEWS.
|
||||
*
|
||||
* First attempt substituted `' . '` and the windows were written `[^<]` — but
|
||||
* collapsed text contains no `<` at all, so the window was bounded by nothing
|
||||
* and leapt three block boundaries to join an `<h2>Q.Arb</h2>` to a paragraph
|
||||
* reading "took effect on 1 March 2025" — approved copy that ships. Measured by
|
||||
* `adversarial-reviewer`.
|
||||
*
|
||||
* Writing the windows `[^.<]` instead would fix that and reintroduce the defect
|
||||
* the collapsed view exists for: a real sentence period inside one paragraph
|
||||
* ("Qualified Arbitrator. Newly commenced") must still be crossable.
|
||||
*
|
||||
* A sentinel separates the two jobs. `[^<\uE000]` is bounded by `<` in the
|
||||
* published view and by `\uE000` in the collapsed one; neither character occurs
|
||||
* in the other view, and a full stop bounds neither. Every window in PATTERNS
|
||||
* uses that class.
|
||||
*/
|
||||
const BLOCK_BOUNDARY = '\uE000'; // Private Use Area: never occurs in real content,
|
||||
// and unlike \u0000 it is not a control character, which `no-control-regex` bars.
|
||||
|
||||
function collapsedText(html) {
|
||||
return publishedText(html)
|
||||
.replace(BLOCK_TAGS, BLOCK_BOUNDARY)
|
||||
.replace(/<[^>]+>/g, ' ')
|
||||
.replace(/[ \t]+/g, ' ');
|
||||
}
|
||||
|
||||
function contextAt(text, index, length) {
|
||||
const from = Math.max(0, index - 55);
|
||||
const to = Math.min(text.length, index + length + 55);
|
||||
@@ -404,7 +552,15 @@ function selfTest() {
|
||||
);
|
||||
}
|
||||
for (const negative of FIXTURES.mustNotMatch) {
|
||||
const hits = scan(publishedText(negative), p.re);
|
||||
/* ⚠️ BOTH VIEWS. This read `publishedText` only, which left the entire
|
||||
false-positive surface of `collapsedText` untested — and that is
|
||||
exactly where the loosening happened: the collapsed view leapt three
|
||||
block boundaries onto approved copy and the instrument check could not
|
||||
see it. Found by `adversarial-reviewer`. */
|
||||
const hits = [
|
||||
...scan(publishedText(negative), p.re),
|
||||
...scan(collapsedText(negative), p.re),
|
||||
];
|
||||
if (hits.length > 0) {
|
||||
failures.push(
|
||||
`${p.id}: matched APPROVED copy — ${JSON.stringify(hits[0].match)} in ${JSON.stringify(negative)}`,
|
||||
@@ -483,14 +639,41 @@ console.log(` pages: ${pages.length}\n`);
|
||||
for (const p of PATTERNS) {
|
||||
const hits = [];
|
||||
for (const page of pages) {
|
||||
const text = publishedText(readFileSync(page, 'utf8'));
|
||||
for (const hit of scan(text, p.re)) {
|
||||
hits.push({
|
||||
page: rel(page),
|
||||
line: lineOf(text, hit.index),
|
||||
match: hit.match,
|
||||
context: contextAt(text, hit.index, hit.match.length),
|
||||
});
|
||||
const raw = readFileSync(page, 'utf8');
|
||||
/* ⚠️ DEDUPE BY OCCURRENCE COUNT, NEVER BY TEXT. The first version keyed a
|
||||
Set on the matched string, so `He is a lawyer.` twice on one page was
|
||||
reported ONCE and the count said 1 — the check truncating its own
|
||||
output, which is the one thing CLAUDE.md says a check must never do.
|
||||
Measured by `adversarial-reviewer` on a two-line fixture.
|
||||
|
||||
The published view is authoritative; the collapsed view only ever ADDS
|
||||
occurrences the tags hid, so a collapsed hit counts only where it exceeds
|
||||
what the published view already found for that same text. */
|
||||
const counted = new Map();
|
||||
const bump = (key) => {
|
||||
const n = (counted.get(key) ?? 0) + 1;
|
||||
counted.set(key, n);
|
||||
return n;
|
||||
};
|
||||
const publishedCounts = new Map();
|
||||
for (const [viewIndex, text] of [
|
||||
publishedText(raw),
|
||||
collapsedText(raw),
|
||||
].entries()) {
|
||||
for (const hit of scan(text, p.re)) {
|
||||
const key = hit.match.replace(/\s+/g, ' ').trim().toLowerCase();
|
||||
if (viewIndex === 0) {
|
||||
publishedCounts.set(key, (publishedCounts.get(key) ?? 0) + 1);
|
||||
} else if (bump(key) <= (publishedCounts.get(key) ?? 0)) {
|
||||
continue;
|
||||
}
|
||||
hits.push({
|
||||
page: rel(page),
|
||||
line: lineOf(text, hit.index),
|
||||
match: hit.match,
|
||||
context: contextAt(text, hit.index, hit.match.length),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user