feat: Q.Arb is held; strike C.Med-Arb entirely; dissolve the paired disclosure
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:
Pouya Lajevardi
2026-08-30 10:37:19 -04:00
co-authored by Claude Opus 5
parent 79b19a7bd0
commit 610edc24fd
20 changed files with 1063 additions and 606 deletions
+19 -25
View File
@@ -29,8 +29,11 @@
* 3. `priceRange` — omitted until `/fees/` exists (build step 9). docs/04
* gates it on that page being real.
*
* AND Q.Arb IS NOT IN `hasCredential`. It commenced August 2026 and is not
* held. Q.Med is. That asymmetry is the whole point of the property.
* AND `hasCredential` NOW CARRIES BOTH DESIGNATIONS. It was Q.Med-only until
* 2026-08-29 because Q.Arb was a commenced pathway and the property means
* *holds*. Q.Arb is held (§4), so it belongs there — and the field is built by
* mapping `CREDENTIALS.designations` rather than indexing it, so a designation
* added to §4 and to that constant cannot be silently omitted here.
*/
import {
CONTACT,
@@ -55,21 +58,11 @@ export const SERVICE_ID = `${SITE.url}/#practice`;
* counterpart row for a completed arbitration**, so "arbitrator" as a practised
* role asserted something the register does not hold.
*
* AND IT CARRIES THE Q.Arb STAGE. Same finding, and it is the sharper half:
* §4 Offerings permits the arbitration offering only while the site states the
* stage of the arc plainly — "neither half may be dropped". The VISIBLE page
* satisfied that with the fourth credential slot; this graph asserted
* arbitration twice (here and in `serviceType`) and stated the stage nowhere.
* A machine-readable claim is still a claim.
*
* `hasCredential` stays Q.Med-only regardless — the stage belongs in prose, not
* in a field that means "holds".
*
* Every clause traces: Q.Med [verified], the JD [verified], engineering
* practice [verified], Toronto [verified], the Q.Arb pathway commenced August
* 2026 [verified]. It claims no licensure and implies none — D13 bars
* implication as hard as assertion, and a crawler summary is a place where an
* implication travels unedited.
* A MACHINE-READABLE CLAIM IS STILL A CLAIM, which is why this description is
* audited like visible copy. Every clause traces: Q.Med and Q.Arb [verified], the JD [verified],
* engineering practice [verified], Toronto [verified]. It claims no licensure
* and implies none — D13 bars implication as hard as assertion, and a crawler
* summary is a place where an implication travels unedited.
*/
export function personNode(
imageUrl?: string,
@@ -87,21 +80,22 @@ export function personNode(
jobTitle: PRACTICE_JOB_TITLE,
description:
'Mediator in Toronto, accepting commercial arbitration appointments. ' +
'Q.Med designation through ADRIC and ADRIO; the Q.Arb pathway commenced ' +
'in August 2026. JD, Bond University; practising machine-learning and ' +
'infrastructure engineer.',
'Q.Med and Q.Arb designations through ADRIC and ADRIO. JD, Bond ' +
'University; practising machine-learning and infrastructure engineer.',
knowsLanguage: ['en', 'fa'],
alumniOf: { '@type': 'CollegeOrUniversity', name: 'Bond University' },
// Q.Med only. See the header comment.
hasCredential: {
/* MAPPED, NOT INDEXED. This read `designations[0]` while Q.Arb was a
pathway; indexing is what would have left Q.Arb out of the graph
silently when §4 changed. */
hasCredential: CREDENTIALS.designations.map((name) => ({
'@type': 'EducationalOccupationalCredential',
name: CREDENTIALS.designations[0],
name,
credentialCategory: 'Professional designation',
recognizedBy: [
{ '@type': 'Organization', name: 'ADR Institute of Canada' },
{ '@type': 'Organization', name: 'ADR Institute of Ontario' },
],
},
})),
sameAs: [CONTACT.linkedin],
email: `mailto:${CONTACT.email}`,
/* `memberOf` — OPT-IN, AND ONLY `/about/` OPTS IN. Q53, ruled by Pouya
@@ -211,7 +205,7 @@ export function professionalServiceNode(imageUrl?: string) {
description:
'Commercial mediation and arbitration for construction, technology, ' +
'energy, insurance, shareholder and cross-border disputes. Toronto, ' +
'by appointment. Q.Med held; the Q.Arb pathway commenced August 2026.',
'by appointment. Q.Med and Q.Arb designations held.',
provider: { '@id': PERSON_ID },
areaServed: [
{ '@type': 'City', name: 'Toronto' },
+74 -28
View File
@@ -47,23 +47,21 @@ export const SITE = {
* licence — and do not imply it either. See AGENTS.md §4 Forbidden.
*/
export const CREDENTIALS = {
designations: ['Q.Med (ADRIC / ADRIO)'],
inProgress: ['Q.Arb — commenced August 2026'], // [verified 2026-08-26]
/**
* "Chartered Med-Arbitrator" — ADRIO's own term, and ADRIC's navigation label
* too (docs/reference/adrio-designations.md; docs/reference/adric-rules.md
* Finding 3, which corroborates it from a second body). Never
* "Mediator-Arbitrator".
* BOTH ARE HELD. Q.Arb joined this list on 2026-08-29 (AGENTS.md §4,
* `[verified 2026-08-29 — Pouya]`); it was `inProgress` before that.
*
* `GOAL_NAME` IS THE STRING TO RENDER. This designation's name was wrong on a
* public page for the life of the file, and the reason it survived four review
* passes is that it existed in several hand-typed copies rather than one
* constant. `/arbitration/` and `/med-arb/` (step 4) render `GOAL_NAME`;
* `/about/`'s arc still hand-types it, which is the remaining copy.
* ⚠️ NO ACQUISITION DATE IS PUBLISHED for either, and this file does not hold
* one. §4 is the only record of when Q.Arb was obtained — a second copy here
* is a copy that goes stale, and §4 currently carries an OPEN conflict on
* that date (Q55). Do not resolve it by writing a date into this file.
*
* There is NO `inProgress` KEY, and its absence is the mechanism. Nothing is
* in progress, and a key that exists is a key a page will eventually render —
* deleting it makes reaching for one a build error rather than a copy defect.
* Same pattern as the deleted `class` prop.
*/
goal: 'C.Med-Arb (Chartered Med-Arbitrator)',
/** Just the expansion, for prose. §11 Glossary is the authority for it. */
goalName: 'Chartered Med-Arbitrator',
designations: ['Q.Med (ADRIC / ADRIO)', 'Q.Arb (ADRIC / ADRIO)'],
education: ['JD, Bond University'],
certifications: [
'Kompass Arbitration Certificate Program',
@@ -365,6 +363,22 @@ export const CONDUCT_UNDERTAKINGS = {
'than left open.',
} as const; // [verified 2026-08-29 — Pouya, Q54]
/**
* THE HELD-DESIGNATIONS SENTENCE, RENDERED AND NEVER RETYPED.
*
* `/about/` and `/med-arb/` both make this claim in prose, and in the change
* set that introduced both they had ALREADY diverged — "the Q.Med and Q.Arb
* designations through" versus "Q.Med and Q.Arb through". Two hand-typed forms
* of the highest-stakes claim on the site is the shape `ASYMMETRY_LINE` exists
* to prevent. Found by `adversarial-reviewer` 2026-08-30.
*
* It is a CLAUSE, not a sentence, because the two pages continue it
* differently. Each supplies its own tail; neither restates the head.
*/
export const DESIGNATIONS_HELD_LINE =
'I hold Q.Med and Q.Arb through the ADR Institute of Canada and the ADR ' +
'Institute of Ontario';
/** The three credential slots. Never matter counts — AGENTS.md §4. */
export const CREDENTIAL_ROW = [
{ value: 'Q.Med', label: 'ADRIC / ADRIO designation' },
@@ -392,24 +406,22 @@ export const CREDENTIAL_ROW = [
* The FOURTH credential slot — separate on purpose, so a three-slot layout
* cannot be handed four by accident and a page has to opt in.
*
* docs/03: 'Fourth slot where the layout has one: Q.Arb — commenced August
* 2026. Use that wording, not "in progress"' — the weaker form drifts toward
* 'nearly complete', which §4 Forbidden bars outright.
* ⚠️ IT IS NO LONGER REQUIRED ANYWHERE. Until 2026-08-29 this slot carried
* `Q.Arb / Commenced August 2026` and §4's paired-disclosure condition made it
* mandatory on any page offering arbitration. Q.Arb is held, that condition is
* dissolved, and the slot reverts to what §4's substitution principle always
* wanted it for: a fourth credential where the layout has room.
*
* REQUIRED on any page that offers arbitration, not decorative. §4 Offerings
* carries a paired-disclosure condition: the site may make the offering only
* while 'stating the second plainly', and 'neither half may be dropped'. The
* footer's designation strip satisfies it site-wide; a page whose opening
* sentence says 'arbitrator' should not make the reader scroll to the footer
* for the stage.
*
* The em-dash in docs/03's string is carried by the layout (value over label),
* not by the text. Same wording, same pairing.
* The label is the ISSUING BODIES, matching `designations` above — not a date.
* §4 records July 2026 and keeps it off the site.
*/
export const CREDENTIAL_ROW_ARB = {
value: 'Q.Arb',
label: 'Commenced August 2026',
} as const; // [verified 2026-08-26 — Pouya]
/* IDENTICAL TO `CREDENTIAL_ROW[0].label`. These two render side by side on `/`
and `/arbitration/`; 'ADRIC / ADRIO' beside 'ADRIC / ADRIO designation'
reads as a distinction that is not being drawn. */
label: 'ADRIC / ADRIO designation',
} as const; // [verified 2026-08-29 — Pouya]
/** Analytics: privacy-first and cookieless (D15). No GA4, no consent banner. */
export const ANALYTICS = {
@@ -671,6 +683,40 @@ export type _MembershipParity = _AssertTrue<
: false
>;
/**
* ⚠️ THE VISIBLE CREDENTIAL ROW HAND-TYPES THE DESIGNATIONS, AND THIS PINS IT.
*
* `CREDENTIALS.designations` feeds the footer strip, `/about/`'s designation
* line, `/about/`'s Designations list and `hasCredential`. `CREDENTIAL_ROW[0]`
* and `CREDENTIAL_ROW_ARB` carry the same two facts decomposed into
* `value`/`label` for `/` and `/arbitration/`, and nothing connected them —
* so a third designation added to §4 and to `designations` would reach four
* surfaces and silently miss the credential row.
*
* That was survivable while the fourth slot held a STAGE (`Commenced August
* 2026`), which was an independent fact. On 2026-08-29 it became a duplicate of
* `designations[1]`, which is what made the two constants drift-capable.
* `adversarial-reviewer` caught that the map-not-index fix celebrated in
* `schema.ts` and `docs/04` left this copy untouched.
*
* A type-level assertion rather than a refactor: the row's `value`/`label`
* shape is a LAYOUT decision (value over label, two-up on a phone) and
* collapsing it into the prose strings would be the wrong fix. This fails
* `npm run check` with a named type the moment the two disagree.
*/
type _DesignationValue<S> = S extends `${infer V} (${string})` ? V : never;
export type _DesignationRowParity = _AssertTrue<
_DesignationValue<
(typeof CREDENTIALS.designations)[0]
> extends (typeof CREDENTIAL_ROW)[0]['value']
? _DesignationValue<
(typeof CREDENTIALS.designations)[1]
> extends (typeof CREDENTIAL_ROW_ARB)['value']
? true
: false
: false
>;
/**
* The five process steps. **HERE, NOT IN THE PAGE**, for the reason written
* against PRACTICE_AREAS above and applied by `adversarial-reviewer` 2026-08-27: