Pouya's rulings: Q44 (memberships current — ship the group), Q45 (PDF bio deferred to step 9), Q46(a) (three offerings pass all gates), Q46(b) (§11 ratified as the source for definitional expansions, conditional on committing the source), Q47 (set jobTitle and worksFor), the legal-advice formulation ratified without change, and Q22 closed on his own execution evidence. Q46(b): docs/reference/adrio-designations.md commits all five ADRIO expansions with reproducible sha256 (four fetches each; both review agents independently reproduced every digest). It immediately caught the error Pouya raised in the same message — §11 had said "Chartered Mediator-Arbitrator" since the file was created, ADRIO's term is "Chartered Med-Arbitrator", and the wrong form was in dist/about/index.html. Four prior review passes read that string and checked only whether it was sourced, not whether it was right. Q47 REVERTED after both review agents struck it independently. jobTitle shipped for one pass as "Mediator and Commercial Arbitrator" — the string claims-auditor had removed from this same node's description the previous day, since §4 has no row for a completed arbitration. The implementation flagged the wrong defect: it argued about scoping and missed that the whole string was already struck. worksFor was reverted because ProfessionalService.provider is this Person, so provider -> Person -> worksFor asserts a same-entity claim transitively. Now jobTitle: 'Mediator', no worksFor. Q49 asks for the two §4 rows. Q44: memberships render with NO currency warranty (his condition), and R10 is re-armed with an event trigger rather than a date since he declined renewal-date tracking. Q22: §7 goes to PROVISIONED; R17 carries the first rotation date, 2026-11-26. New CLAUDE.md convention, his: never suppress stderr in a verification script — suppression turns "it failed" into "it found nothing". Two review rounds resolved 48 findings; the majority of the second round were defects in the first round's fixes, including a re-widening of §4's renewal period inside the comment that corrects that widening, a cited guard in schema.ts that does not exist, and a struck §9 row describing a reverted state. Three findings were one lift from a public page: docs/03's /for-parties/ directive breached D13 twice, docs/01 told an implementer an unpublishable strip could ship, and docs/07 priced three ungated offerings with no gate note. Also commits docs/reference/adrio-extract/ — the extraction script and its five outputs, since the digests covered raw HTML and said nothing about the text the term counts were run against. The equivalent gap for Q22's IAM verification is NOT closed and is Q52. Verified: astro check 0/0/0, eslint + prettier clean, build 2 pages, 0 .js emitted, minifier guard silent, animation-timeline intact, no currency-warranty phrasing in dist, JSON-LD correct on both pages. NOT run: Lighthouse (tool unavailable until step 7, R11); HTML validator. Opens Q48-Q53. Live reminders: R1, R10, R11, R13, R14, R15, R16, R17. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0148NztQskLKKApP5SzAA78e
709 lines
33 KiB
TypeScript
709 lines
33 KiB
TypeScript
/**
|
||
* Site-wide constants.
|
||
*
|
||
* Anything marked TODO(pouya) is an unanswered question in AGENTS.md §9.
|
||
* Do not guess a value to make the build pass — an unanswered question is
|
||
* supposed to be visible. See CLAUDE.md.
|
||
*/
|
||
|
||
export const SITE = {
|
||
name: 'Pouya Lajevardi',
|
||
tagline: 'Mediation · Arbitration · Toronto',
|
||
url: 'https://adr.smlcompany.ca',
|
||
locale: 'en_CA',
|
||
/**
|
||
* The footer's copyright line, in full. Q30 is CLOSED.
|
||
*
|
||
* Two facts were being conflated in the string this replaces
|
||
* (`'SML Company Ltd. · Ontario, Canada'`), which read as a jurisdiction of
|
||
* incorporation and named the wrong one:
|
||
*
|
||
* - Jurisdiction of incorporation — **federal, under the CBCA**
|
||
* `[verified 2026-08-26 — Pouya]`, recorded in AGENTS.md §4.
|
||
* - Place of business — Toronto, Ontario. That is `CONTACT.location`,
|
||
* and it belongs in the contact block, not in the entity line.
|
||
*
|
||
* **Neither appears in the footer.** Pouya's direction, 2026-08-26: the line
|
||
* is `© <year> SML Company Ltd` and nothing else. The incorporation fact is
|
||
* verified and available — it is simply not published. Do not "complete" this
|
||
* line by adding it back.
|
||
*
|
||
* No corporation number: we do not have one and the line does not need one.
|
||
*
|
||
* Spelling note so it does not read as a typo and get "fixed": AGENTS.md §4
|
||
* writes *SML Company Ltd.* with a terminal period. Pouya specified the
|
||
* rendered footer string twice, both times without it. His wording governs
|
||
* what ships.
|
||
*/
|
||
entity: 'SML Company Ltd',
|
||
} as const;
|
||
|
||
/**
|
||
* Verified credentials only — mirrors AGENTS.md §4.
|
||
* Adding a line here without adding it there is a bug.
|
||
*
|
||
* D13: the site asserts the JD and makes NO licensure claim. Do not add
|
||
* 'lawyer', 'called to the bar', 'licensed', or any post-nominal implying a
|
||
* 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
|
||
* (docs/reference/adrio-designations.md). This read "Chartered
|
||
* Mediator-Arbitrator" until 2026-08-28, which was wrong; Pouya caught it and
|
||
* it was his own error, carried from the strategy brief and never sourced.
|
||
*
|
||
* UNCONSUMED AS OF 2026-08-28 — nothing imports `CREDENTIALS.goal`. `/about/`'s
|
||
* credential arc hand-types all three designations instead, which is the drift
|
||
* shape this repo keeps paying for (see ContactBand's 52ch/46ch divergence).
|
||
* It is corrected rather than deleted because `/med-arb/` at build step 4 is
|
||
* its natural consumer: either that page uses it, or this line comes out.
|
||
*/
|
||
goal: 'C.Med-Arb (Chartered Med-Arbitrator)',
|
||
education: ['JD, Bond University'],
|
||
certifications: [
|
||
'Kompass Arbitration Certificate Program',
|
||
/* "sequence", NOT "series" — §4: "Stitt Feld Handy negotiation and ADR
|
||
workshop **sequence** — completed". This list said "series" while the bio
|
||
prose on the same page said "sequence": one certification, two names, one
|
||
page. Found by `claims-auditor` 2026-08-28. Same shape as the C.Med-Arb
|
||
error — a third-party programme name that four review passes read without
|
||
checking it was right. */
|
||
'Stitt Feld Handy — negotiation and ADR workshop sequence',
|
||
],
|
||
languages: ['English', 'Farsi'],
|
||
/**
|
||
* [verified 2026-08-28 — Pouya, AGENTS.md Q44] — re-stamped when Q44 closed;
|
||
* the original confirmation was 2026-08-26 (Q28 plus 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, quoted exactly: *"the OBA sections and the CTF renew
|
||
* yearly"* — NOT "Both the OBA sections…", which is how this comment quoted it
|
||
* until 2026-08-28. The substance was right and the quotation marks were not,
|
||
* in the comment written to stop a widened paraphrase of this exact sentence.
|
||
* Found by `claims-auditor`. 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.
|
||
*
|
||
* **PUBLISHED FROM 2026-08-28 — Q44 CLOSED.** Pouya re-confirmed all four as
|
||
* current, which discharges R10's prohibition, and `/about/` now renders a
|
||
* Memberships group from this array. Re-stamped `[verified 2026-08-28 —
|
||
* Pouya]`; the earlier stamp was 2026-08-26.
|
||
*
|
||
* ⚠️ **RENDER THE LIST; NEVER RENDER A CLAIM ABOUT ITS CURRENCY.** No
|
||
* "renewed annually", no "current as of", no "listed as current", no stamp
|
||
* date in the markup. Pouya's ruling: *"List the memberships; promise nothing
|
||
* about their future state. The list is a snapshot, and only §4's stamp says
|
||
* when it was taken."* He declined renewal-date tracking, so there is no date
|
||
* behind such a sentence and nothing in this repo could support one.
|
||
*
|
||
* R10 stays live and now fires on an **event** rather than a date: re-confirm
|
||
* before any cutover or major republish. OCNI is why — §4 carries it as lapsed
|
||
* and unpublishable, and that was found roughly a year late.
|
||
*
|
||
* 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)',
|
||
'Ontario Bar Association — Construction & Infrastructure, ADR, and Civil Litigation sections',
|
||
'Canadian Tax Foundation',
|
||
],
|
||
} as const;
|
||
|
||
/**
|
||
* The Toronto boutique is NEVER named — AGENTS.md D16. Use this string.
|
||
* Do not infer a name from an email domain or anywhere else.
|
||
*/
|
||
export const BOUTIQUE = 'a Toronto litigation and ADR boutique' as const;
|
||
|
||
/**
|
||
* The boutique role and the litigation line — the two highest-risk strings on
|
||
* the site, so they live here rather than being typed into a page.
|
||
*
|
||
* Neither had a constant until 2026-08-26, which meant `/about/` (step 3) and
|
||
* the `Person` JSON-LD (docs/04) were both going to hand-type them. A claim
|
||
* written by hand in a component is a claim nobody re-checks against §4 — and
|
||
* these are the two where the wording IS the compliance.
|
||
*/
|
||
export const ROLE = {
|
||
/**
|
||
* §4 verbatim, and it is the VISIBLE role only.
|
||
*
|
||
* NO LONGER THE JSON-LD `jobTitle` — Q47, ruled 2026-08-28. This string was
|
||
* both the visible role line and the Person node's `jobTitle`, which put
|
||
* "Director of Firm Operations" on a node whose `url` is this ADR practice's
|
||
* `/about/` — so a consumer could attach the boutique title to this entity.
|
||
* Pouya's ruling splits them: the graph carries PRACTICE_JOB_TITLE below,
|
||
* while this string stays exactly where it was in visible copy ("I am
|
||
* {ROLE.title} at {ROLE.at}").
|
||
*
|
||
* **The graph carries NO `worksFor`.** This sentence said it did — "the graph
|
||
* now carries PRACTICE_JOB_TITLE below and `worksFor: SML Company Ltd`" —
|
||
* which was true for one pass and was reverted the same day (Q49(b)). Verified
|
||
* 2026-08-28: zero live `worksFor` properties in `src`.
|
||
*/
|
||
title: 'Director of Firm Operations', // [verified 2026-08-25 — strategy brief §I]
|
||
/** Always rendered with BOUTIQUE, never with a firm name (D16). */
|
||
at: BOUTIQUE,
|
||
/**
|
||
* D13's approved phrasing, and the only approved phrasing. The alternative
|
||
* he approved is 'involvement in litigation and ADR matters'.
|
||
*
|
||
* NEVER "practice" in this context — that is the exact word D13 bars in the
|
||
* exact context it bars it, and §4 records that this register itself once
|
||
* carried the wrong word here while quoting the strategy brief verbatim.
|
||
* "Practice" describing Pouya's OWN ADR practice is correct and unaffected.
|
||
*
|
||
* Explicitly interim — AGENTS.md R1. Raise it; do not let it settle in.
|
||
*/
|
||
litigationLine: 'active litigation exposure', // [verified 2026-08-26 — D13]
|
||
/** The matter types behind that exposure. §4 verbatim; do not extend this
|
||
* list without a §4 row to extend it from. */
|
||
litigationAreas: [
|
||
'personal injury',
|
||
'construction',
|
||
'regulatory (POA)',
|
||
'insurance (SABS)',
|
||
],
|
||
} as const;
|
||
|
||
/**
|
||
* The Person node's `jobTitle` — Q47, ruled by Pouya 2026-08-28.
|
||
*
|
||
* NOT `ROLE.title`, and that separation IS the ruling. §4's row is one fact with
|
||
* two halves — *"Director of Firm Operations, Toronto litigation and ADR
|
||
* boutique"* — and visible copy always pairs them. The JSON-LD emitted only the
|
||
* first half, on a `Person` whose `url` is this practice's `/about/`, so a
|
||
* consumer could attach the boutique title to this entity. `worksFor` could not
|
||
* fix it, because D16 bars naming the boutique and there was no value it could
|
||
* take.
|
||
*
|
||
* His ruling breaks the bind by changing what the field is about: *"jobTitle
|
||
* describes this practice, not the boutique role, which D16 keeps unnamed"* —
|
||
* and that half holds: this constant names no boutique.
|
||
*
|
||
* **THE `worksFor` HALF OF THE RULING IS NOT IMPLEMENTED — Q49(b).** This
|
||
* paragraph said *"`worksFor` becomes SML Company Ltd — verified, federally
|
||
* incorporated, and the entity the practice operates through. Both are set"*.
|
||
* Two defects, both found by `claims-auditor` on re-audit: **"Both are set" is
|
||
* false** (reverted the same day), and *"the entity the practice operates
|
||
* through"* was listed inside a run of verified attributes when **§4 rows only
|
||
* "Operator of SML Company Ltd. `alongside` the practice"** — a different
|
||
* structural relation, and precisely what Q49(b) is open on. Do not restate the
|
||
* ruling's phrasing as though the register carried it.
|
||
*
|
||
* ⚠️ **IT SHIPPED FOR ONE PASS AS "Mediator and Commercial Arbitrator" AND THAT
|
||
* WAS WRONG FOR A REASON I HAD NOT SEEN.** Both review agents found it
|
||
* independently on 2026-08-28, which is this loop's strongest signal.
|
||
*
|
||
* The string `claims-auditor` struck from **this same node's `description`** on
|
||
* 2026-08-27 was *"Mediator and commercial arbitrator in Toronto"*. The value
|
||
* ruled for `jobTitle` is the same words minus the city — **in the most
|
||
* role-asserting field in the vocabulary**, thirty lines below the comment in
|
||
* `schema.ts` that explains why the words were struck. §4 verifies *"Has
|
||
* completed multiple sole mediations"* and has **no counterpart row for a
|
||
* completed arbitration** — only that appointments are *accepted*. Consumers
|
||
* render `jobTitle` beside `name`: *Pouya Lajevardi — Mediator and Commercial
|
||
* Arbitrator*, which invites the reader to supply a track record for both halves.
|
||
*
|
||
* **I flagged the wrong thing.** My note argued about scoping ("Commercial"),
|
||
* and neither the note nor I noticed the whole string had already been struck on
|
||
* different grounds. A flag aimed at the wrong defect reads as diligence and
|
||
* provides none.
|
||
*
|
||
* **So this ships as the narrowest form §4 actually rows**, and Q47's purpose is
|
||
* still served: Pouya's ruling was that `jobTitle` describe *this practice*
|
||
* rather than the boutique role, and "Mediator" does exactly that. Nothing is
|
||
* lost from the graph — `description` ("accepting commercial arbitration
|
||
* appointments") and `serviceType` ("Commercial arbitration") both carry the
|
||
* arbitration **offering**, and both cleared audit. Only the role-assertion is
|
||
* gone.
|
||
*
|
||
* **AGENTS.md Q49 asks Pouya for the row.** If he wants the fuller title it
|
||
* needs either a §4 row for arbitrator-as-practised-role, or an offering-shaped
|
||
* value — `adversarial-reviewer` proposed `'Mediator; accepts commercial
|
||
* arbitration appointments'`, which is honest and reads oddly for a job title.
|
||
* His call, not one to take by tidying.
|
||
*/
|
||
// [derived from §4 — "Q.Med designation through ADRIC / ADRIO" + "Has completed
|
||
// multiple sole mediations". NOT a row stamp: §4 has no row reading "Mediator",
|
||
// and the row-level wording is what Q49(a) is open on. The 2026-08-25 date this
|
||
// comment first carried was inherited from ROLE.title's row.]
|
||
export const PRACTICE_JOB_TITLE = 'Mediator' as const;
|
||
|
||
/* `PRACTICE_ENTITY` LIVED HERE FOR ONE PASS AND IS DELETED WITH `worksFor`.
|
||
*
|
||
* It existed only to populate `Person.worksFor`, which is withheld pending a §4
|
||
* row (Q49). `adversarial-reviewer` found the defect that decided it, and it is
|
||
* one the "name only, nothing else" scoping did **not** address: the
|
||
* ProfessionalService node's `provider` **is** this Person, so
|
||
* `provider → Person → worksFor → SML Company Ltd` asserts transitively exactly
|
||
* what `src/pages/about.astro` declines to assert in prose — that the practice
|
||
* and the company are the same entity. **The referent matters and the first
|
||
* version of this sentence got it wrong:** it said "the comment four lines above
|
||
* it", pointing at `aboutGraph`'s note in `schema.ts`, which covers
|
||
* `ProfilePage`, `BreadcrumbList` and `memberOf` and says **nothing** about SML
|
||
* Company Ltd. `adversarial-reviewer` read it and found the citation empty —
|
||
* *"a claim whose referent cannot be reached is unverifiable by construction"*,
|
||
* this repo's own rule, applied to the argument for a revert. The real referent
|
||
* is `about.astro`'s deleted sentence: *"the company through which the
|
||
* engineering work is done" — a corporate-structure claim.* The transitive
|
||
* argument stands on its own; the evidence offered for it did not.
|
||
*
|
||
* Two further grounds, both recorded so this is not re-added casually:
|
||
* - §4's row says "Operator of SML Company Ltd **alongside** the practice".
|
||
* Q47's ruling says "the entity the practice **operates through**". Those are
|
||
* different structural relations and the second has no §4 row.
|
||
* - `/about/` already **removed** a sentence of this exact class from visible
|
||
* copy — see about.astro: *"the company through which the engineering work is
|
||
* done" — a corporate-structure claim*. Publishing it machine-readably while
|
||
* declining it in prose is the stricter-in-public, looser-in-metadata shape.
|
||
*
|
||
* The original omission had TWO grounds — "either names the boutique (D16) **or
|
||
* misstates the employer**". Q47 answers the first. The second is Q49.
|
||
*
|
||
* `SITE.entity` already carries the string for the footer. Re-adding a second
|
||
* constant for the same name would be the drift this file keeps paying for.
|
||
*/
|
||
|
||
/**
|
||
* 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' },
|
||
/**
|
||
* Q37 CLOSED 2026-08-27. This label read 'Law and engineering' and it is now
|
||
* 'Legal training and engineering practice'. Pouya's reasoning, kept because
|
||
* it is the finding rather than the fix:
|
||
*
|
||
* "The parallel was doing the implying — a degree and a practice under one
|
||
* noun. The asymmetry is the honest part."
|
||
*
|
||
* A JD is a degree. Engineering is a practice, and a verified one (§4).
|
||
* Setting the two in parallel invited the reader to supply the symmetry, and
|
||
* for 'Law' the missing half is a licence — which D13 bars by implication as
|
||
* hard as by assertion.
|
||
*
|
||
* IT IS DELIBERATELY LOPSIDED AND LONGER. Do not tidy it back into a
|
||
* parallel, and do not shorten it to fit a layout; change the layout.
|
||
*/
|
||
{ value: 'JD + ML', label: 'Legal training and engineering practice' },
|
||
{ value: 'EN · FA', label: 'Bilingual practice' },
|
||
] as const;
|
||
|
||
/**
|
||
* 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.
|
||
*
|
||
* 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.
|
||
*/
|
||
export const CREDENTIAL_ROW_ARB = {
|
||
value: 'Q.Arb',
|
||
label: 'Commenced August 2026',
|
||
} as const; // [verified 2026-08-26 — Pouya]
|
||
|
||
/** Analytics: privacy-first and cookieless (D15). No GA4, no consent banner. */
|
||
export const ANALYTICS = {
|
||
/**
|
||
* Q31 CLOSED — **Plausible**, decided rather than defaulted. Pouya checked
|
||
* 2026-08-26: Fathom is Canadian-owned but stores non-EU traffic on US
|
||
* servers, isolating in the EU only for EU visitors; Plausible keeps all data
|
||
* in the EU. For a practice whose privacy posture is part of the offer,
|
||
* EU-only beats US-hosted. D15 amended to match.
|
||
*
|
||
* The union type stays — `/legal/privacy/` has to name the processor, and a
|
||
* change of processor is a copy change on that page, not just a config edit.
|
||
*/
|
||
provider: 'plausible' as 'plausible' | 'fathom',
|
||
domain: 'adr.smlcompany.ca',
|
||
} as const;
|
||
|
||
export const CONTACT = {
|
||
email: 'info@smlcompany.ca', // [verified 2026-08-26]
|
||
/** No public phone by choice. Render 'By scheduled call' wherever a number
|
||
* would go — do not leave the field visually empty. */
|
||
phone: null as string | null, // [verified 2026-08-26]
|
||
phoneFallback: 'By scheduled call',
|
||
location: 'Toronto · Ontario · By appointment',
|
||
/** [verified 2026-08-26 — Pouya, AGENTS.md Q27]. A PUBLIC COMMITMENT: this
|
||
* wording must match /contact/, the inquirer confirmation email, and any
|
||
* bio. Change it here and sweep — never edit one copy. */
|
||
responseTime: 'Inquiries are answered within two business days.',
|
||
/** The same fact in sentence-fragment form, for the confirmation email and
|
||
* any inline use. Derived, so the two cannot drift. */
|
||
responseTimeShort: 'within two business days',
|
||
linkedin: 'https://www.linkedin.com/in/pouyalajevardi/', // [verified 2026-08-26]
|
||
/** Booking parked 2026-08-26 (AGENTS.md R6). Build /contact/ with the intake
|
||
* form and a reserved slot so an embed drops in later without a rebuild. */
|
||
bookingUrl: null as string | null,
|
||
} as const;
|
||
|
||
/** Portrait assets. Astro derives AVIF/WebP variants from the master at build. */
|
||
export const PORTRAIT = {
|
||
master: 'src/assets/pouya-lajevardi.jpg', // 1600x1600
|
||
og: 'src/assets/og-portrait.jpg', // 1200x630, cropped high
|
||
alt: 'Pouya Lajevardi',
|
||
} as const;
|
||
|
||
/** Shown on /contact/ and with the booking embed. Do not reword casually. */
|
||
export const NO_RETAINER_NOTICE =
|
||
'Submitting this form does not create a retainer, does not appoint a neutral, ' +
|
||
'does not itself establish a mediator–party relationship, and does not itself ' +
|
||
'create a conflict check.';
|
||
|
||
/**
|
||
* Rate card — AGENTS.md D14, confirmed by Pouya 2026-08-26.
|
||
* One rate for all mediation matters. All figures PLUS HST.
|
||
* Full research and reasoning: docs/07-fees.md
|
||
*/
|
||
export const FEES = {
|
||
currency: 'CAD',
|
||
taxNote: 'All fees are plus HST.',
|
||
mediation: {
|
||
/** Prep is bundled AND stated on the page — [verified 2026-08-26].
|
||
* Do not hide it: at these rates, saying preparation is included is the
|
||
* point, not a detail. */
|
||
halfDay: { amount: 2000, hours: 3.5, prepIncluded: 2 },
|
||
fullDay: { amount: 4000, hours: 7, prepIncluded: 3 },
|
||
additionalParty: 500, // each party beyond two
|
||
overtimePerHour: 500, // [verified 2026-08-26]
|
||
},
|
||
arbitration: {
|
||
perHour: 500,
|
||
hearingDay: 4000,
|
||
documentsOnlySimple: 6500, // flat
|
||
documentsOnlyComplex: 9500, // flat
|
||
// No tribunal-secretary rate — removed by Pouya 2026-08-26.
|
||
},
|
||
/**
|
||
* 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.' },
|
||
{ window: '15 to 30 days before', fee: '50% of the booked fee.' },
|
||
{ window: 'Fewer than 15 days before', fee: '100% of the booked fee.' },
|
||
],
|
||
cancellationNotes: [
|
||
'Rescheduling at the time of cancellation, with a new date fixed, is not charged.',
|
||
'The cancellation fee is waived if the reserved time is filled by another matter of equal or greater value.',
|
||
],
|
||
terms: [
|
||
'Fees are shared equally between the parties unless they agree otherwise in writing.',
|
||
'Accounts are payable on rendering. Interest accrues on overdue accounts at 5% per annum.',
|
||
'Video and in-person sessions are charged at the same rate.',
|
||
],
|
||
} as const;
|
||
|
||
/**
|
||
* Slugs as their own literal tuple so consumers keep the union type.
|
||
* Deriving them with `.map()` and casting to `[string, ...string[]]` widens
|
||
* them back to `string`, and a mistyped slug then survives `astro check`.
|
||
*/
|
||
export const PRACTICE_SLUGS = [
|
||
'construction',
|
||
'technology',
|
||
'energy',
|
||
'insurance',
|
||
'shareholder',
|
||
'cross-cultural',
|
||
] as const;
|
||
|
||
export type PracticeSlug = (typeof PRACTICE_SLUGS)[number];
|
||
|
||
/**
|
||
* The six areas, with the one-line blurb each card renders.
|
||
*
|
||
* THE BLURBS LIVE HERE, not in the pages, because `/` and `/practice/` both
|
||
* render them and two copies of a claim-bearing sentence is one copy that will
|
||
* eventually be wrong. Same reasoning as ROLE and CREDENTIAL_ROW above.
|
||
*
|
||
* EVERY BLURB IS DISPUTE TYPES, NOT HISTORY. docs/03: "Frame as positioning,
|
||
* not as history" — 'Built to facilitate ... on Ontario's megaproject pipeline',
|
||
* never 'extensive experience resolving'. AGENTS.md §4 (Q35, 2026-08-27) makes
|
||
* that condition 2 of the publication gate for naming a practice area at all.
|
||
* A blurb that claims volume fails the gate even though the label passes.
|
||
*
|
||
* Nothing here may carry a count, a value, a settlement rate, or a superlative
|
||
* (§4 Forbidden). Dispute types are not claims of caseload.
|
||
*/
|
||
export const PRACTICE_AREAS = [
|
||
{
|
||
slug: 'construction',
|
||
name: 'Construction & Infrastructure',
|
||
chip: 'Construction',
|
||
blurb:
|
||
'Liens, delay and change-order claims, scheduling, subcontract and ' +
|
||
"deficiency disputes. Built for Ontario's megaproject pipeline.",
|
||
},
|
||
{
|
||
slug: 'technology',
|
||
name: 'Technology, AI & Data',
|
||
chip: 'Technology',
|
||
blurb:
|
||
'Software contracts, SLA and MSA breakdowns, data residency and ' +
|
||
'processing, AI vendor diligence, IP and licensing.',
|
||
},
|
||
{
|
||
slug: 'energy',
|
||
name: 'Energy, Grid & Regulatory',
|
||
chip: 'Energy',
|
||
blurb:
|
||
'Grid connection and allocation, leave-to-construct, ' +
|
||
'proponent–municipality disputes, IESO market participation.',
|
||
},
|
||
{
|
||
slug: 'insurance',
|
||
name: 'Insurance, SABS & LAT',
|
||
chip: 'Insurance',
|
||
/**
|
||
* Q41(c) CLOSED 2026-08-27 — and the verification changed the wording again.
|
||
*
|
||
* `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 alongside a LAT application, before filing or after.',
|
||
},
|
||
{
|
||
slug: 'shareholder',
|
||
name: 'Shareholder & Family Business',
|
||
chip: 'Shareholder',
|
||
/**
|
||
* "Family Business" means COMMERCIAL disputes among family shareholders.
|
||
* The blurb says "family-held companies" and names commercial dispute types
|
||
* for that reason — AGENTS.md Q39, 2026-08-27.
|
||
*
|
||
* The explicit exclusion — family law matters are not accepted — belongs on
|
||
* the PAGE, one sentence, at build step 5 (docs/01 §/practice/shareholder/).
|
||
* Pouya scoped it there. Do not add it to this blurb: on a six-card grid it
|
||
* unbalances the row and reads defensively, and the wording here already
|
||
* makes the area unambiguously commercial.
|
||
*/
|
||
blurb:
|
||
'Shareholder and partnership disputes, co-founder breakdowns, and ' +
|
||
'business succession in family-held companies.',
|
||
},
|
||
{
|
||
slug: 'cross-cultural',
|
||
name: 'Cross-Border & Diaspora',
|
||
chip: 'Cross-cultural',
|
||
blurb:
|
||
'Diaspora business succession, dual-jurisdiction shareholder disputes, ' +
|
||
'and cross-cultural commercial matters. Conducted in English or Farsi.',
|
||
},
|
||
] as const satisfies ReadonlyArray<{
|
||
slug: PracticeSlug;
|
||
name: string;
|
||
chip: string;
|
||
blurb: string;
|
||
}>;
|
||
|
||
/**
|
||
* Compile-time completeness check, both directions.
|
||
*
|
||
* `satisfies` above catches a slug in PRACTICE_AREAS that is not in
|
||
* PRACTICE_SLUGS. This catches the reverse — a slug with no area — which would
|
||
* otherwise let an article declare a practice area that has no page, no nav
|
||
* child and no chip, producing a dead link at step 7. Deriving the areas from
|
||
* the slugs used to make that structurally impossible; keeping two literals is
|
||
* what buys the literal types back, so the check has to be explicit.
|
||
*
|
||
* Type-only. Nothing runs, nothing ships.
|
||
*/
|
||
type _AssertNever<T extends never> = T;
|
||
type _SlugsWithoutAnArea = Exclude<
|
||
PracticeSlug,
|
||
(typeof PRACTICE_AREAS)[number]['slug']
|
||
>;
|
||
export type _SlugCoverage = _AssertNever<_SlugsWithoutAnArea>;
|
||
|
||
/**
|
||
* 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:
|
||
* `/` renders a compressed strip of these and `/process/` renders them in full
|
||
* at build step 6, so a copy typed into one page is a copy that will eventually
|
||
* disagree with the other. The proof is already in the history — the step-3 body
|
||
* below carried a fee claim that the same session's claims audit found to be
|
||
* wrong against `docs/07`, and it existed in exactly one place. After step 6 it
|
||
* would have existed in two.
|
||
*
|
||
* TIMINGS ARE `docs/01` §`/process/`'s, verbatim: "confidential intake (day 0) ·
|
||
* engagement and framing (1–7) · pre-session exchange (7–21) · the session
|
||
* (21–30) · 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.
|
||
* "Binding conclusion" alone would read as though a mediation binds, which it
|
||
* does not until the parties sign.
|
||
*
|
||
* NO FEE CLAIM IN ANY BODY. `docs/07` bundles a CAPPED preparation allowance
|
||
* (2 h in the half day, 3 h in the full day) and says in terms that it "must be
|
||
* stated on the page... Do not quietly fold it into the hours figure." A
|
||
* five-word strip cannot state it properly, and stating it improperly
|
||
* misdescribes money. `/fees/` at step 9.
|
||
*/
|
||
export const PROCESS = [
|
||
{
|
||
title: 'Confidential intake',
|
||
timing: 'Day 0',
|
||
body: 'A scheduled call to scope the matter, identify the parties, and run conflicts.',
|
||
},
|
||
{
|
||
title: 'Engagement and framing',
|
||
timing: 'Days 1–7',
|
||
body: 'Terms of appointment, the issues in dispute, and who attends.',
|
||
},
|
||
{
|
||
title: 'Pre-session exchange',
|
||
timing: 'Days 7–21',
|
||
body: 'Briefs and documents, exchanged in advance so the session starts informed.',
|
||
},
|
||
{
|
||
title: 'The session',
|
||
timing: 'Days 21–30',
|
||
body: 'Half day or full day, in person or by video.',
|
||
},
|
||
{
|
||
title: 'Conclusion',
|
||
timing: 'Day 30 onward',
|
||
body: 'Minutes of settlement — or an award, where the process is arbitral.',
|
||
},
|
||
] 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 21–30` 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' },
|
||
{ href: '/mediation/', label: 'Mediation' },
|
||
{ href: '/arbitration/', label: 'Arbitration' },
|
||
{ href: '/practice/', label: 'Practice', children: PRACTICE_AREAS },
|
||
{ href: '/fees/', label: 'Fees' },
|
||
{ href: '/insights/', label: 'Insights' },
|
||
{ href: '/contact/', label: 'Contact' },
|
||
] as const;
|
||
|
||
/** Linked contextually rather than from the primary nav. */
|
||
export const SECONDARY_NAV = [
|
||
{ href: '/process/', label: 'How I work' },
|
||
{ href: '/med-arb/', label: 'Med-Arb' },
|
||
{ href: '/for-parties/', label: 'For parties' },
|
||
] as const;
|
||
|
||
export const LEGAL_NAV = [
|
||
{ href: '/legal/privacy/', label: 'Privacy' },
|
||
{ href: '/legal/terms/', label: 'Terms' },
|
||
] as const;
|