feat: build step 3 — /about/, minus its memberships; close Q40–Q43
Build and deploy / build-and-deploy (push) Failing after 6s

Applies Pouya's rulings on Q42, Q41(a)(b)(c), Q43 and Q40, then builds
`/about/` — six of docs/01's seven items.

`/about/` ships WITHOUT a memberships group. R10 is a prohibition on
shipping a page that lists memberships before they are re-confirmed; the
re-confirmation is a fact only Pouya holds and was not obtained. The
first version published all four and disclosed the gap in five places
instead; both review agents rejected that. Q44 carries the question.

Rulings:
- Q42 — ENE, dispute-system design and pre-dispute technical advisory
  rowed; settlement counsel struck as a partisan role. The strike
  exposed a hole in the offering test, which now states the prior
  question it was missing.
- Q41(a) — Q37 reaches prose, and prose is held to a higher bar. The
  sentence is now one constant, ASYMMETRY_LINE, because two hand-typed
  copies had already diverged inside one session.
- Q41(b) — not restored; the implication turned out to be in three
  places, two of which survived the sweep that closed it.
- Q41(c) — verified against the LAT's own Rules and extracted into
  docs/reference/lat-case-conference.md. Rule 2.4 makes "Pre-Hearing
  Conference" the Tribunal's own term for a case conference; the Rules
  contain zero occurrences of `mediat` in 66,593 characters.
- Q43 — the timings are service commitments; PROCESS_FRAMING renders
  adjacent to them, not in a lede above.
- Q40 — bundled to step 7 as R15, blocking cutover.

Four review passes, 43 findings, nine of them defects in their own
predecessors' fixes. The worst was mine: the false universal Q39 struck
reached a public page. Also fixed a portrait ladder that upscaled 1.93x
at 1024/DPR2 on BOTH pages — the shipped home page included — because
its 960 ceiling was derived from the layout range where the image is
narrowest.

Verified: check/lint/build/audit clean; 0 upscaling across 11 device
profiles; 0 overflow and 0 over-wide elements at 13 widths; 0 contrast
failures across 127 and 88 painted pairs; 0 print failures against white
paper; reveal 0 hidden under reduced-motion and print; zero JavaScript.
Lighthouse NOT RUN — tool unavailable until step 7 (R11). HTML validator
NOT RUN.

Opens Q44 (memberships), Q45 (PDF bio), Q46 (offering-test gating; the
glossary standard), Q47 (jobTitle without worksFor). Adds R15.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0148NztQskLKKApP5SzAA78e
This commit is contained in:
Pouya Lajevardi
2026-08-28 12:10:41 -04:00
co-authored by Claude Opus 5
parent 165d259f5c
commit c576b9a85f
17 changed files with 2603 additions and 147 deletions
+44
View File
@@ -139,3 +139,47 @@ export function homeGraph(imageUrl?: string) {
'@graph': [professionalServiceNode(imageUrl), personNode(imageUrl)],
};
}
/**
* `/about/`'s graph — build step 3. This is where PERSON_ID actually resolves:
* every other page references `/about/#person`, and until now nothing served it
* from that URL.
*
* ONE NODE, AND THREE ADDITIONS WERE CONSIDERED AND DECLINED. Each is a
* decision rather than an omission, recorded so the next reader does not
* "complete" it:
*
* 1. `ProfilePage` as a wrapper, with `mainEntity` → Person. Accurate, and
* Google documents it. Declined: docs/04's structured-data table lists
* `Person` for this page and does not list `ProfilePage`, and a type not in
* the spec is a deviation that needs a reason. The marginal gain is not
* one. Revisit in docs/04, not here.
* 2. `BreadcrumbList`. docs/04 requires it on "all nested pages" and says it
* must MATCH VISIBLE BREADCRUMBS. `/about/` is one hop from the root, has
* no visible breadcrumb, and the header nav marks it as current — so
* emitting one would assert a navigation structure the page does not show.
* Breadcrumbs begin at the two-level pages: `/practice/<area>/`, `/insights/<slug>/`.
* 3. `memberOf` for the four memberships. Declined on R10 / **Q44** — and
* the visible page reached the same answer one round later, which is worth
* recording: `/about/` now publishes **no memberships group at all**,
* because R10 is a prohibition on shipping such a page and the
* re-confirmation was not obtained. So this field is not a stricter
* standard than the page; it is the same one.
*
* Two earlier versions of this comment were wrong on the facts. They said
* "the page publishes them visibly" (it does not, as of 2026-08-28) and
* "all four renew yearly" — §4 records yearly renewal for **the OBA
* sections and the CTF only** and says nothing about ADRIC or ADRIO. The
* widened form had propagated to four files.
*
* The reason a machine-readable membership claim is worse than a visible
* one stands regardless: a list on a page is corrected by editing the page,
* while a scraped claim is cached and re-served by systems that never
* re-read it. OCNI lapsed quietly once already. Add this when Q44 closes.
*/
export function aboutGraph(imageUrl?: string) {
return {
'@context': 'https://schema.org',
'@graph': [personNode(imageUrl)],
};
}
+124 -19
View File
@@ -56,12 +56,31 @@ export const CREDENTIALS = {
'Stitt Feld Handy — negotiation and ADR workshop series',
],
languages: ['English', 'Farsi'],
/** [verified 2026-08-26 — Pouya, AGENTS.md Q28 and the CTF addition of the
* same date] — and FOR NOW. Both the OBA sections and the Canadian Tax
* Foundation renew yearly, so every line below is a fact with a shelf life
* (AGENTS.md R10). Re-confirm at renewal, and before any page that lists
* memberships ships. NOT OCNI (lapsed) and NOT the Law Society — listing the
* LSO implies licensure, which D13 bars. Do not add either. */
/**
* [verified 2026-08-26 — Pouya, AGENTS.md Q28 and the CTF addition of the same
* date] — and FOR NOW.
*
* WHAT §4 ACTUALLY SAYS ABOUT RENEWAL, because a widened version of it reached
* a public page. §4: *"Both the OBA sections and the CTF renew yearly."* It
* says **nothing** about ADRIC's or ADRIO's renewal period. An earlier form of
* this comment read "Both the OBA sections and the Canadian Tax Foundation
* renew yearly, so every line below is a fact with a shelf life", which is two
* claims joined by a "so" that does not follow — and the widened form
* ("all four renew annually") then propagated into `schema.ts`, into
* `/about/`, and into §9 Q44. Exactly the SES-DKIM duplication shape: the copy
* that goes stale is the one nobody re-reads, and this copy became public copy.
*
* **NOT PUBLISHED AS OF 2026-08-28 — R10 / Q44.** R10 requires a
* re-confirmation *"before any page listing memberships ships"*, `/about/` is
* that page, and the re-confirmation is a fact only Pouya holds. It was not
* obtained, so `/about/` ships its Credentials section WITHOUT a memberships
* group and carries a `TODO(pouya)`. Do not render this array on a public page
* until Q44 closes.
*
* NOT OCNI (lapsed — §4: "not current, do not publish") and NOT the Law
* Society: listing the LSO implies licensure, which D13 bars. Do not add
* either.
*/
memberships: [
'ADR Institute of Canada (ADRIC)',
'ADR Institute of Ontario (ADRIO)',
@@ -114,6 +133,33 @@ export const ROLE = {
],
} as const;
/**
* THE Q41(a) SENTENCE. It lives here for the reason `ROLE` above lives here:
* *"these are the two where the wording IS the compliance."*
*
* It was hand-typed into `/` and then into `/about/`, and **the two copies had
* already diverged** — `/` used a comma ("one side, a working engineering
* practice on the other"), `/about/` used full stops — within the same session
* that wrote both. This is the sentence Q41(a) makes responsible for making the
* licence implication *"impossible rather than merely absent"*, so a silent
* divergence in it is the highest-consequence drift on the site.
*
* Pouya's ruling, 2026-08-27, kept because it is the finding rather than the fix:
*
* "The implication test applies everywhere, not just to labels. Prose has more
* room, so it is easier to satisfy: state the asymmetry explicitly rather than
* relying on a parallel construction to carry it."
*
* Deleting the parallel is only half of it — a reader supplies the missing
* symmetry from silence, and for the legal half the missing half is a licence.
* Naming that half **training** is what forecloses it. Do not tidy this into a
* parallel, do not shorten it to fit a layout, and do not retype it into a page.
*/
export const ASYMMETRY_LINE =
'The two halves are not the same kind of thing, and the asymmetry is the ' +
'honest part. A law degree on one side. A working engineering practice on ' +
'the other. One is training I hold. The other is work I still do.';
/** The three credential slots. Never matter counts — AGENTS.md §4. */
export const CREDENTIAL_ROW = [
{ value: 'Q.Med', label: 'ADRIC / ADRIO designation' },
@@ -233,7 +279,15 @@ export const FEES = {
documentsOnlyComplex: 9500, // flat
// No tribunal-secretary rate — removed by Pouya 2026-08-26.
},
// ENE, settlement counsel, dispute-system design, pre-dispute technical advisory
/**
* THREE services at this rate, not four. Q42 CLOSED 2026-08-27 by Pouya:
* early neutral evaluation, dispute-system design, and pre-dispute technical
* advisory each gained a §4 Offerings row; **settlement counsel was REMOVED**
* — his words: *"Settlement counsel acts FOR a party in negotiation. That is
* a partisan role, and putting it on a site that (a) sells neutrality and
* (b) asserts no licensure under D13 is wrong twice over."* Do not restore
* it, and do not price it.
*/
hourly: 500, // [verified 2026-08-26]
cancellation: [
{ window: 'More than 30 days before', fee: 'No fee. Disbursements only.' },
@@ -313,19 +367,38 @@ export const PRACTICE_AREAS = [
name: 'Insurance, SABS & LAT',
chip: 'Insurance',
/**
* "LAT pre-hearing mediation" was flagged by `claims-auditor` 2026-08-27:
* `docs/01` §`/practice/insurance/` lists that phrase as a SEARCH INTENT,
* not as an offering, and as a service blurb it reads as conducting
* mediation inside the LAT's own statutory process — which is not what a
* privately retained neutral is appointed to do.
* Q41(c) CLOSED 2026-08-27 — and the verification changed the wording again.
*
* Reworded to the offering that is actually rowed in §4 (mediation) applied
* to the subject matter that is actually verified (insurance / SABS).
* Q41 asks Pouya to confirm the intent before the page ships at step 5.
* `LAT pre-hearing mediation` (a SEARCH INTENT in `docs/01`, never an
* offering) must never be published. Pouya's ruling: *"imprecise and must
* not imply appointment by the tribunal. Verify against LAT's own materials
* how its case-conference process is conducted and who conducts it."*
*
* Verified 2026-08-28 against the LAT Rules and the LAT-AABS process page,
* both extracted into `docs/reference/lat-case-conference.md`:
*
* - Rule 2.4: *"'Case Conference' has the same meaning as 'Pre-Hearing
* Conference' as defined in the SPPA."* **"Pre-hearing" is the
* Tribunal's own label**, and what it names is a case conference.
* - Rule 14.3: a **Member** presides, and is then disqualified from the
* hearing panel. Rule 14.6: parties must attend. The neutral is the
* Tribunal's, and a privately retained one cannot be appointed to it.
* - The Rules contain **zero** occurrences of `mediat` or `arbitrat`
* (0 in 66,593 characters). The concept is not in them.
*
* The interim read "private mediation of matters before the LAT", which is
* ambiguous in the one word that matters: `before` reads as *pending at* as
* easily as *prior to*. Replaced with the temporal frame the Tribunal's own
* page endorses — *"you may want to consider negotiation or mediation
* services... before filing at the LAT-AABS, and continuing... after a
* claim has been filed."*
*
* `/practice/insurance/` at step 5 must say the mediation is PRIVATE and is
* not the Tribunal's case conference.
*/
blurb:
'Accident benefits and SABS entitlement, MIG disputes, and private ' +
'mediation of matters before the LAT.',
'mediation alongside a LAT application, before filing or after.',
},
{
slug: 'shareholder',
@@ -392,9 +465,25 @@ export type _SlugCoverage = _AssertNever<_SlugsWithoutAnArea>;
*
* TIMINGS ARE `docs/01` §`/process/`'s, verbatim: "confidential intake (day 0) ·
* engagement and framing (17) · pre-session exchange (721) · the session
* (2130) · binding conclusion (30+)". `docs/03` §Process requires them REAL
* rather than illustrative, so they are not softened to "typically" — and they
* are not invented either. **They have no §4 row; that is Q43.**
* (2130) · binding conclusion (30+)".
*
* **Q43 CLOSED 2026-08-27, and the ruling went the other way from this
* comment's previous reasoning.** It read: *"`docs/03` §Process requires them
* REAL rather than illustrative, so they are not softened to 'typically'."*
* Pouya ruled that the five timings are **service commitments, the same class
* as Q27's response time** — not facts about him, so they need framing rather
* than a Verified row:
*
* "Present them as the TYPICAL shape of an engagement, explicitly not a
* guarantee: mediation timing depends on party and counsel availability,
* which he does not control. Published as typical, they are honest and
* useful; published as commitments, the first matter that slips makes the
* page false."
*
* The NUMBERS ARE UNCHANGED — softening was never the fix, and inventing them
* was never on. What changed is that they now ship with `PROCESS_FRAMING`
* below, which is **not optional**: any page rendering these steps renders it
* too. `docs/03` §Process has been amended to record the override.
*
* Step 5 is labelled from the spec but its body says what actually concludes —
* minutes of settlement in a mediation, an award where the process is arbitral.
@@ -435,6 +524,22 @@ export const PROCESS = [
},
] as const;
/**
* THE FRAMING THAT MAKES THE TIMINGS PUBLISHABLE — Q43, Pouya 2026-08-27.
*
* Not decoration and not a disclaimer bolted on: it is the condition on which
* the five numbers above may appear at all. *"Published as typical, they are
* honest and useful; published as commitments, the first matter that slips
* makes the page false."*
*
* RENDER IT ADJACENT TO THE STEPS, on every page that renders them — `/` now,
* `/process/` at step 6. A reader who sees `Days 2130` and not this sentence
* has read a commitment. First person, per `docs/03` §Voice.
*/
export const PROCESS_FRAMING =
'This is the typical shape of an engagement, not a commitment. Timing ' +
'depends on party and counsel availability, which I do not control.';
/** Seven items is the ceiling before a nav stops being scannable. */
export const PRIMARY_NAV = [
{ href: '/about/', label: 'About' },