feat: build step 1 — scaffold, layout, header, footer, SEO; zero JavaScript

Build order step 1 (docs/01): scaffold, tokens, base layout, header,
footer, SEO component, plus a temporary /type-scale/ proof sheet that
step 2 deletes.

THE FONTS WERE NEVER ON DISK. global.css declared six @font-face rules
pointing at /fonts/*.woff2 and public/fonts/ did not exist, so every
face had been silently falling back to Georgia and the system sans.
Six cuts committed, 123,804 bytes, SIL OFL 1.1, provenance in
docs/reference/fonts-provenance.md. ?v=1 on every URL because the
deploy script serves them immutable for a year.

ZERO JAVASCRIPT. The reveal was an inline IntersectionObserver in
<head>; docs/05 specifies script-src 'self' with no unsafe-inline, so
the only script on the site was the one thing the site's own CSP would
refuse to execute. Replaced with animation-timeline: view() behind
@supports. 0 script tags and 0 .js files in dist.

The infinity mark is lifted verbatim from the deployed site's own
smlMark loading thumbnail, not redrawn (Q32 asks whether a canonical
vector exists). The proof sheet computes its contrast table from
tokens.css rather than restating docs/02 — all eleven ratios reproduce
the measured table exactly.

Register: Canadian Tax Foundation added (§4, R10 widened); Q30 closed
— SML Company Ltd is federally incorporated under the CBCA, and the
footer publishes neither that nor the place of business; Q31 closed —
Plausible, on EU-only data residency (D15 amended). ROLE constants
added for "Director of Firm Operations" and "active litigation
exposure" so step 3 does not hand-type them.

Lighthouse unavailability now stated in six places rather than left as
a control that had silently stopped existing (§7, R11).

Both review agents ran twice. The second pass found four defects in
the first pass's fixes, including the minifier bug written back into
its own fix and a colour-alone repair that used the banned gold-on-
cream pairing at 2.10:1. Measured in headless Chrome at thirteen
widths with a seventh nav item injected: 0 overflow, 0 tap targets
under 44x44, 0 focus-order inversions, state indicators at 12.29:1,
755 words of body text with no JavaScript.

Opened: Q32-Q37. Closed: Q30, Q31.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XquaEq4BgWMCwUqLEyNkF
This commit is contained in:
Pouya Lajevardi
2026-08-26 15:57:02 -04:00
co-authored by Claude Opus 5
parent 8f1df2c27c
commit 8134709548
33 changed files with 2575 additions and 147 deletions
+308 -16
View File
@@ -52,19 +52,43 @@ is built to be added to continuously, not shipped once. `[verified 2026-08-25]`
The site live at `adr.smlcompany.ca` as of this entry: `[verified 2026-08-25]`
> ⚠️ **Several of these measurements are contested — see Q34 (opened
> 2026-08-26).** A re-fetch of the deployed URL that day reproduced some of the
> list exactly and could not reproduce others *from the served HTML*, because
> the served document turns out to be a bundler harness whose application lives
> in nine UUID-named script files that were not fetched. **Do not cite any
> figure below as established, and do not put one in public copy, until Q34
> closes.** The items marked ⚠️ are the specific ones in doubt. This caveat sits
> here rather than only in §9 because a reader who arrives at a `[verified]`
> stamp will otherwise never learn it is under review.
- It is a **single 2.2 MB HTML file** containing an entire React application,
compiled **in the browser at runtime** by Babel Standalone loaded from unpkg.
- React and ReactDOM are loaded as **development** builds from a public CDN.
*Confirmed on re-fetch 2026-08-26: the response is **2,206,032 bytes**, of
which **2,210,921** are inline `<script>`.*
- ⚠️ React and ReactDOM are loaded as **development** builds from a public CDN.
*Not reproducible 2026-08-26: the served file contains no reference to
`unpkg` or to a React development build. They may be inside the unfetched
bundles. Q34.*
- **Crawlers see almost nothing.** A server-side fetch of the URL returns only
`SML Company`, `DISPUTE RESOLUTION`, and the loading string `Unpacking...`.
Every word of real content is assembled client-side after three CDN round
trips. `[verified 2026-08-25 — direct fetch]`
- The deployed `<head>` has **no `<meta name="viewport">`**, no meta
description, no Open Graph or Twitter card tags, no canonical URL, and no
favicon. `[verified 2026-08-25]`
favicon. `[verified 2026-08-25]` — *still true of the head a crawler parses.
Note for accuracy: the harness carries a second, JSON-escaped `<head>` inside
a `<script type="__bundler/template">` which does contain a viewport tag. It
is assembled by JavaScript, so it reaches a browser and not a crawler, which
is the distinction that matters here.*
- `robots.txt` returns **403**. There is no sitemap. `[verified 2026-08-25]`
- The two logo PNGs are ~1 MB combined and are **base64-inlined** into the HTML,
so they cannot be cached separately from the page. `[verified 2026-08-25]`
- ⚠️ The two logo PNGs are ~1 MB combined and are **base64-inlined** into the
HTML, so they cannot be cached separately from the page. `[verified
2026-08-25]` — **but a 2026-08-26 fetch found zero `base64,` occurrences
anywhere in the served document.** Q34. This figure is cited as the *reason*
for a standing convention in `CLAUDE.md` and `docs/02`, both of which now
carry the caveat. A related number, "470 KB PNG", appeared in `docs/02` with
no source anywhere in this repo and has been removed.
- `<title>` is still `SML Company · Dispute Resolution` — the pre-rebrand
placeholder title. `[verified 2026-08-25]`
- There is **no version control, no build step, and no test suite**. The
@@ -102,7 +126,7 @@ without an explicit instruction and a Change Log entry. `[verified 2026-08-25]`
| D12 | Agent working file | **This file**, maintained under the constitution above | Ad hoc notes |
| D13 | Licensure claims | **The site asserts the JD only.** No claim of licensure, call to the bar, or entitlement to practise law. The approved phrasing for the boutique role is **"active litigation exposure"** or **"involvement in litigation and ADR matters"** — never "practice" **in that context**. "Practice" describing Pouya's own ADR practice — "the dispute resolution practice of Pouya Lajevardi" — is correct and stays. Pouya's direction, 2026-08-26. **Explicitly interim — see Standing Reminders §12** | Stating LSO licence status; the word "practice" |
| D14 | Fee structure | **Single published rate card, all mediation matters at one rate.** Confirmed by Pouya 2026-08-26; figures in `docs/07-fees.md`. No tribunal-secretary line | Two-tier card (recommended by Claude, declined); ranges; fees on request |
| D15 | Analytics | **Privacy-first and cookieless** (Plausible or Fathom). No cookie banner, nothing to consent to, one line in the privacy policy | GA4; no analytics at all |
| D15 | Analytics | **Plausible.** Privacy-first and cookieless: no cookie banner, nothing to consent to, one line in the privacy policy. *Amended 2026-08-26 (Q31):* the original read "Plausible **or** Fathom", i.e. undecided, and a guessed `'plausible'` had already leaked into `src/data/site.ts` from it. **Decided, not defaulted** — Pouya checked rather than assumed and found his own assumption wrong: Fathom is Canadian-owned, which is the intuitive answer here, but it stores non-EU traffic on **US servers** and isolates 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, and ownership is not the axis that matters | GA4; no analytics at all; **Fathom** — rejected on data residency, not on quality |
| D18 | Intake email | **Two emails per submission** — notification to `info@smlcompany.ca`, and a **confirmation receipt to the inquirer**. Pouya, 2026-08-26. The receipt is what requires SES production access (Q19) | Notification only; no email; no form at all |
| D17 | Working method | **Pouya architects; Claude Code implements and then adversarially reviews its own work.** Six-phase loop encoded in `.claude/commands/build.md`; two independent review agents in `.claude/agents/`; extended thinking on by default. Standing agreement — not restated per prompt | Implement-and-report; single generic reviewer; review only on request |
| D16 | Naming the boutique | **Never named.** Referred to throughout as *a Toronto litigation and ADR boutique*. Pouya's decision, 2026-08-26 | Naming the firm |
@@ -155,7 +179,8 @@ since May.
| Bilingual English and Farsi | `[verified 2026-08-25 — strategy brief §I]` |
| Iranian-Canadian; cross-cultural fluency with diaspora business communities | `[verified 2026-08-25 — strategy brief §I]` |
| Operator of SML Company Ltd. alongside the practice | `[verified 2026-08-25 — strategy brief §I]` |
| Memberships: **ADRIC**, **ADRIO**, and **OBA — Construction & Infrastructure, ADR, and Civil Litigation sections** | `[verified 2026-08-26 — Pouya]`, **for now**. Section membership renews yearly; this is a fact with a shelf life, tracked as R10 |
| **SML Company Ltd — incorporated FEDERALLY, under the CBCA** | `[verified 2026-08-26 — Pouya, Q30]`. Two facts were being conflated and one of them was wrong: **jurisdiction of incorporation is federal (Canada)**; **place of business is Toronto, Ontario**. `src/data/site.ts` carried `'SML Company Ltd. · Ontario, Canada'`, which reads as a jurisdiction of incorporation and named the wrong one. **No corporation number** — none is held and the line does not need one. **Caution, and it is the point of this row:** "federally incorporated" says nothing about professional licensure, and nothing about where the practice may operate. It must not be read together with the **Licence status — NOT ESTABLISHED** row into an implication that neither row makes. **Not published:** on Pouya's direction the footer reads `© <year> SML Company Ltd` and nothing further — the fact is verified and available, it is simply not on a page |
| Memberships: **ADRIC**, **ADRIO**, **OBA — Construction & Infrastructure, ADR, and Civil Litigation sections**, and the **Canadian Tax Foundation** | `[verified 2026-08-26 — Pouya]`, **for now**. *CTF added 2026-08-26.* Both the OBA sections and the CTF renew yearly; every line here is a fact with a shelf life, tracked as R10. Re-confirm at renewal and before any page listing memberships ships. **CTF is a membership, not a practice area** — it is the one credential none of the six areas touch, and `docs/01-architecture.md` records why there is no seventh page at launch and when to revisit (R3) |
| ~~OCNI~~ | **Not current. Do not publish** `[verified 2026-08-26 — Pouya]` |
| ~~LSO~~ | **Do not publish.** Listing the Law Society among memberships implies licensure, which D13 bars. Excluded deliberately, not by oversight `[verified 2026-08-26]` |
| Toronto, Ontario; by appointment | `[verified 2026-08-26]` |
@@ -237,12 +262,12 @@ the audience it targets. Revisit at month 1218. `[verified 2026-08-25 — dec
|---|---|
| Framework | **Astro 7.2.7**, `output: 'static'` `[verified 2026-08-26 — npm view astro version, D1 as amended]`. `@astrojs/mdx` 7.0.8, `@astrojs/sitemap` 3.7.3, `sharp` 0.35.4 |
| Lint toolchain | ESLint **10.9.1**, `@eslint/js` 10.0.1, `globals` 17.11.0, `eslint-plugin-astro` **3.1.0**, `eslint-plugin-jsx-a11y` 6.10.2, `typescript-eslint` 8.68.0, `typescript` 5.9.3 — **every pin at the registry's `latest` except `typescript`** `[verified 2026-08-26 — npm view, all 14 pins]`. `@eslint/js` and `globals` are declared explicitly; before 2026-08-26 `eslint.config.js` imported them and they resolved only by npm hoisting accident. **Accessibility linting is on**`flat/jsx-a11y-recommended`, 36 rules `[verified 2026-08-26 — 7 rules fired on a deliberately inaccessible .astro file]`. `eslint-plugin-jsx-a11y@6.10.2` declares a stale `eslint ^3..^9` peer range; a one-line `overrides` entry in `package.json` resolves it. ⚠️ **`eslint-plugin-astro@3.1.0` declares `node ^22.22.3 \|\| ^24.16.0 \|\| >=26.3.0`**, which excludes Pouya's Node 25.6.0 — `npm install` prints EBADENGINE there. Dev-time only, and `nvm use` (Node 22 LTS, per `.nvmrc`) clears it. `typescript` is held at 5.x: `typescript-eslint` peers `<6.1.0` and `@astrojs/check` peers `^5 \|\| ^6`, so TypeScript 7.0.2 is unusable here `[verified 2026-08-26 — npm view]` |
| Lighthouse CI | **Not installed.** `@lhci/cli` was the sole source of all 10 `npm audit` findings (7 high, via `lighthouse → puppeteer-core → extract-zip`), 0.15.1 is `latest` so there was no clean upgrade, and it cannot run at all — no pages, no `lighthouserc`. Removed 2026-08-26; **`npm audit` now reports 0 vulnerabilities**. Re-add at build step 7 with a freshly verified pin (R11) `[verified 2026-08-26 — npm audit]` |
| Node | **22 LTS line**, `.nvmrc` holds `22` so it tracks the latest 22.x rather than freezing at a floor. `package.json` declares **`engines.node >=22.13.0`** and **`engines.npm >=9.6.5`** — the intersection of every dependency's own floor: Astro 7 and `@astrojs/mdx` 7 need `>=22.12.0`, ESLint 10 needs `^20.19.0 \|\| ^22.13.0 \|\| >=24` `[verified 2026-08-26 — npm view astro@7.2.7 engines, npm view eslint@10.9.1 engines]`. **Pouya's machine reports Node v25.6.0** `[verified 2026-08-26 — node -v]`, an odd-numbered non-LTS line; it satisfies the floor, but `nvm use` keeps local and CI on the same runtime |
| Lighthouse CI | **Not installed, and that is now stated wherever the check is claimed.** `@lhci/cli` was the sole source of all 10 `npm audit` findings (7 high, via `lighthouse → puppeteer-core → extract-zip`), 0.15.1 is `latest` so there was no clean upgrade, and it cannot run at all — no pages, no `lighthouserc`. Removed 2026-08-26; **`npm audit` now reports 0 vulnerabilities** `[verified 2026-08-26 — npm audit]`. Removing it left a **documented control that no longer exists**`docs/04`, `CLAUDE.md` and `/build` Phase 5 all required a run that had silently become impossible, which is Q22's defect in a different costume. Fixed 2026-08-26: the unavailability is stated in `docs/04-seo-spec.md` (budget table, the callout under Performance, and the post-launch checklist), `CLAUDE.md` (performance budget and the definition of done), `.claude/commands/build.md` Phase 5, `docs/06-deployment.md` (PR checks and the cutover checklist), and `.claude/agents/adversarial-reviewer.md` §4 — which is also told **not** to raise the absence as a finding. **Re-add at build step 7** with a pin verified that day and a check for a patched release; do not assume 0.15.1 is still the ceiling (R11) |
| Node | **22 LTS line**, `.nvmrc` holds `22` so it tracks the latest 22.x rather than freezing at a floor. `package.json` declares **`engines.node` = `^22.13.0 || >=24`** (verbatim — it excludes Node 23, an EOL odd line, which a flat `>=22.13.0` would have admitted) and **`engines.npm >=9.6.5`** — the intersection of every dependency's own floor: Astro 7 and `@astrojs/mdx` 7 need `>=22.12.0`, ESLint 10 needs `^20.19.0 \|\| ^22.13.0 \|\| >=24` `[verified 2026-08-26 — npm view astro@7.2.7 engines, npm view eslint@10.9.1 engines]`. **Pouya's machine reports Node v25.6.0** `[verified 2026-08-26 — node -v]`, an odd-numbered non-LTS line; it satisfies the floor, but `nvm use` keeps local and CI on the same runtime |
| Styling | Plain CSS with custom properties. No Tailwind, no CSS-in-JS `[verified 2026-08-25]` |
| Client JS | Astro islands only, where genuinely needed. Target: most pages ship zero JS `[verified 2026-08-25]` |
| Client JS | **Zero. Not "minimal" — none.** `dist/type-scale/index.html` contains **0 `<script>` tags** and `dist/_astro/` contains no JS bundle `[verified 2026-08-26 — built, counted, and confirmed in headless Chrome]`. The reveal was an inline `IntersectionObserver` in `<head>` until 2026-08-26; it was removed because `docs/05-backend-spec.md` specifies `script-src 'self'` with no `unsafe-inline`, so the only script on the site was the one thing the site's own CSP would refuse to run. `animation-timeline: view()` in `global.css` replaces it. **Both scroll-driven animations must use `animation-*` LONGHANDS** — Lightning CSS folds the `animation` shorthand together with `animation-timeline` into an invalid declaration and discards it, which works in `npm run dev` and is dead in `npm run build`. It happened twice in one session: once in the header condense, then again in the fix written for it. `/build` Phase 5 now greps `dist` for it. Islands remain available where a feature genuinely cannot be CSS or progressive HTML — none has been needed |
| Content | Astro **Content Layer API** collections, MDX for Insights. Config lives at **`src/content.config.ts`**; collections declare a `loader`, not a `type`; `z` imports from `astro/zod`. **Astro 5 introduced** the Content Layer API and this location; **Astro 6 removed** the legacy `src/content/config.ts` fallback — moving the file back now raises `LegacyContentConfigError` `[verified 2026-08-26 — reproduced by moving it back]` |
| Fonts | Instrument Serif + Geist + Geist Mono, **self-hosted**, `font-display: swap` `[verified 2026-08-25]` |
| Fonts | Instrument Serif + Geist + Geist Mono, **self-hosted**, `font-display: swap`. **Files present as of 2026-08-26** — six `.woff2` cuts, **123,804 bytes** total, in `public/fonts/` (`du -sh` says 136K; that is disk blocks, not transfer, and this row is read in a performance context); provenance, licences (all SIL OFL 1.1) and the reason they are committed rather than pulled at build are in `docs/reference/fonts-provenance.md`. Before this they were *declared* in `global.css` and **absent from disk**, so every face silently fell back to Georgia and the system sans `[verified 2026-08-26 — built and listed]`. Instrument Serif 400 latin (21,032 B) and Geist latin (29,400 B) are preloaded in `BaseLayout.astro` — about 50 kB at first paint; nothing else is. Every font URL carries **`?v=1`**, because the deploy script serves `/fonts/*` `immutable` for a year: replacing a cut means bumping that query in `global.css` and in the preload together `[verified 2026-08-26 — byte counts]` |
| AWS account | `327082975128` `[verified 2026-08-26 — inventory]` |
| Region | **`ca-central-1`** throughout — hosting, Lambda, DynamoDB `[verified 2026-08-26]` |
| S3 bucket | **`adr-smlcompany-site`** — versioning **Enabled**, so rollback works `[verified 2026-08-26]` |
@@ -278,7 +303,7 @@ the audience it targets. Revisit at month 1218. `[verified 2026-08-25 — dec
| **Deploy credential — NOT PROVISIONED** | `aws iam get-user --user-name adr-sml-deploy` returns **NoSuchEntity** `[verified 2026-08-26 — Q22]`. The scoped IAM user does not exist, no access key has been issued, and the Gitea secrets are unset. **No file may describe this credential as existing.** Creation commands are with Pouya; this is a to-do, not an open question |
| **How deploys actually happen today** | **Locally, via `npm run deploy`** (`scripts/deploy-local.sh`) — same guard, same three sync passes, same cache headers, same invalidation as the workflow. Gitea Actions needs `[actions] ENABLED` in `app.ini` and a registered `act_runner`, both of which need the instance's second administrator (Q23). At this scale the pipeline changes only **how a deploy is triggered**, not what it does `[verified 2026-08-26]` |
| **Interim auth — do not repeat in CI** | Pouya has been authenticating as **`user/pouya`**, the broadly-permissioned personal user the Q10 inventory captured. Acceptable for interactive work at a keyboard; **never** as a CI credential — see §10 `[verified 2026-08-26]` |
| Analytics | **Plausible or Fathom** — cookieless, no personal data, no consent banner, EU-hosted `[verified 2026-08-26 — D15]` |
| Analytics | **Plausible** — cookieless, no personal data, no consent banner, **all data held in the EU** `[verified 2026-08-26 — D15 as amended, Q31]`. `src/data/site.ts` sets `ANALYTICS.provider`. Not yet installed: no script is on any page, and `/legal/privacy/` (step 10) is where the processor gets named |
## 8. Design system
@@ -326,8 +351,14 @@ Nothing below can be invented. Each needs an answer from Pouya.
| ~~Q27~~ | **ANSWERED 2026-08-26 — two business days.** A public commitment, so it must read identically everywhere it appears: `src/data/site.ts`, `/contact/`, the inquirer confirmation email, and any bio | — |
| ~~Q28~~ | **ANSWERED 2026-08-26 — OBA Construction & Infrastructure, ADR, and Civil Litigation** `[verified 2026-08-26 — Pouya]`, **for now**: section membership renews yearly, so this is a fact with a shelf life. Tracked as R10 | — |
| ~~Q29~~ | **ANSWERED 2026-08-26 by implementation.** Guard widened on both counts: the two secrets are checked (emptiness only, never echoed), and `INTAKE_ENDPOINT` is promoted to job-level `env:` and guarded. Every `vars.*` and `secrets.*` the workflow consumes is now covered except `BOOKING_URL`, empty by decision (R6) | — |
| **Q30** | **What is SML Company Ltd.'s jurisdiction of incorporation, and should it appear in the footer?** `src/data/site.ts` carried `entity: 'SML Company Ltd. · Ontario, Canada'`. §4 verifies "Operator of SML Company Ltd." and "Toronto, Ontario" — the latter about **Pouya**, not the company's incorporation. Jurisdiction dropped pending an answer; the operator fact stays. Raised by `claims-auditor`, 2026-08-26 | The site-wide footer |
| **Q31** | **Plausible or Fathom?** D15 records the choice as "Plausible **or** Fathom" — undecided. `src/data/site.ts` had `provider: 'plausible'`, a guessed value, in a file whose own header says not to guess one to make the build pass. Set to `null` with a `TODO(pouya)`. Raised by `claims-auditor`, 2026-08-26 | Analytics; the privacy-policy line that names the processor |
| ~~Q30~~ | **ANSWERED 2026-08-26 — federally, under the CBCA**, and it does **not** appear in the footer. Recorded in §4 with the caution that it implies nothing about licensure or about where the practice may operate. The footer reads `© <year> SML Company Ltd` and stops there (Pouya's direction, given twice). `src/data/site.ts` un-nulled, `TODO(pouya)` removed. Note the spelling: §4 writes *SML Company Ltd.* with a terminal period; the rendered string has none, because that is how Pouya specified it | — |
| ~~Q31~~ | **ANSWERED 2026-08-26 — Plausible**, and decided rather than defaulted. Pouya checked and found his own assumption wrong: Fathom is Canadian-owned but stores non-EU traffic on US servers, isolating in the EU only for EU visitors; Plausible holds everything in the EU. D15 amended with that reasoning. The value that was guessed and nulled is now the value that was chosen — which is not the same thing, and the difference is why it was nulled | — |
| **Q35** | **May the header nav and footer sitemap name a service or practice area the register does not establish as a present capability, before the page that qualifies it exists?** This is the architecture-versus-register question that `claims-auditor` has now raised twice, and it is not one an implementer should settle. The nav and footer ship on all nineteen pages and today carry **`Arbitration`**, **`Med-Arb`**, **`Energy, Grid & Regulatory`** and **`Shareholder & Family Business`** — none of which trace to a §4 row. Every one of them is also **locked architecture**: D5 and §6 fix the sitemap, and `docs/01` specifies each page. The specs already anticipate the tension and answer it at page level — `docs/03`: *"Frame as positioning, not as history"*; `docs/01` on energy: *"Write it as a genuine position, not a claim of existing volume"* — so the question is precisely whether a **one-word nav label**, which has no room to frame anything, inherits that licence. Three ways out: accept the labels as taxonomy and rely on the pages to qualify (status quo), rename toward capability-neutral wording, or hold items out of the nav until their page ships. **Claude Code declined to act unilaterally on either audit pass**; recorded so the judgement is visible rather than missed | The header and footer on every page; sharpest at step 5 |
| **Q36** | **Is co-arbitration work available now?** Asserted in three specs — `docs/01` §`/arbitration/`, `docs/03` §Voice as model copy, and `docs/07-fees.md`, which instructs *"The page must say so"* — and **it is in no §4 row.** §4 records the Q.Arb pathway as commenced August 2026 and nothing about what is available in the meantime. The sentence is offered under the heading *"Name the limits"*, so the unverified half travels inside advice about honesty, which is how it survived. All three files now cite this question; none has been deleted, because the *shape* of the sentence is right and only its second clause is unsourced. Raised by `claims-auditor`, 2026-08-26 | `/arbitration/` (step 4) and `/fees/` (step 9) |
| **Q37** | **Is "Law and engineering" the right label under `JD + ML`?** §4's substitution principle supplies the three credential-row **values** (`Q.Med` / `JD + ML` / `EN · FA`); the labels come from `docs/03` and are not themselves registered. `claims-auditor` reads this one as a D13 implication risk: "engineering" is shorthand for a **verified practising** claim, so the parallel invites "Law" to be read the same way, and D13 bars implication as hard as assertion. Left as written — it is approved copy and changing approved copy is not an implementer's call — with a `TODO(pouya)` on it in `src/data/site.ts`. Nothing renders it yet. Raised by `claims-auditor`, 2026-08-26 | The credential row on `/` (step 2) and `/about/` (step 3) |
| **Q33** | **How is arbitration described in site-wide copy before Q.Arb is conferred?** Not a wording question — a positioning one, and it recurs on every page. §4 records the Q.Arb pathway as **commenced August 2026**, "never as held or nearing completion". `SITE.tagline` reads `Mediation · Arbitration · Toronto`, and `docs/01` specifies that exact string as the **Home hero eyebrow** — where the hero copy beneath it can qualify it. Build step 1 promoted it to a masthead line under Pouya's name on every page, where nothing qualifies it and it reads as a designation strip; `claims-auditor` flagged it and **it has been removed from the header**. But the question it exposed is still open and lands at build step 2: does the hero eyebrow keep `Arbitration` as specified, qualify it, or hold it until designation? `/arbitration/` (step 4) is separately specced to state the position plainly, which is the honest model — the issue is the one-line forms that have no room to. **Second pass, same day:** the removal from the header did not sweep the proof sheet, where the same string was **hand-typed** as a type specimen and rendered ten times at up to 96px. Both defects fixed — the specimen is now a neutral pangram — and the lesson is the sweep rule again: a removal is a `grep`, not a memory. The nav item `Arbitration` also survives, deliberately; that is Q35. Raised by `claims-auditor`, 2026-08-26 | The Home hero (step 2); `docs/04`'s specified home `<title>`; any bio or one-line descriptor |
| **Q34** | **Do §2's measurements of the previous build still hold, and were they measured against the deployed file?** Two of `claims-auditor`'s findings were unverified old-site assertions published in copy, which sent Claude Code to measure the live URL on 2026-08-26. What came back does not straightforwardly match §2. **Reproduced:** the response is a single **2,206,032-byte** file, and `<title>` is still `SML Company · Dispute Resolution`. **Could not be reproduced from the served HTML:** there are **zero** `base64,` occurrences anywhere in it — §2 records "two logo PNGs ~1 MB, base64-inlined" — and no reference to `unpkg` or a React development build. **Why this is a question and not a correction:** the served document is a *bundler harness*. 2,210,921 bytes of it are inline `<script>`, the real `<head>` sits JSON-escaped inside a `<script type="__bundler/template">`, and the application is loaded from **nine UUID-named script files that were not fetched**. The logos and the CDN references may well be in those bundles. So §2 may be right, may be stale, or may have been measured against the local source rather than the deployment — this record cannot tell which. **Why it matters beyond tidiness:** `docs/02` and `CLAUDE.md` both cite the base64-logo figure as the *reason* for a standing convention, and §12 R8 exists because unverified premises propagate. Nobody should quote these numbers in public copy until the question closes. Raised by Claude Code, 2026-08-26 | Nothing structural. It governs whether §2's figures may be cited as fact |
| **Q32** | **Is there a canonical vector file for the SML infinity mark?** `src/components/InfinityMark.astro` is built from geometry lifted verbatim from the deployed site's own loading-thumbnail SVG — the element it labels `smlMark`, fetched from `https://adr.smlcompany.ca/` on 2026-08-26. Path, both stroke widths (28 / 6) and the 0.7 inner opacity are the source's; the only change is folding a `translate(60 0)` into the coordinates. So it is SML's own artwork rather than a redrawing — but a loading placeholder is not necessarily the canonical file, and D7 says the mark carries over *unchanged*. If a master SVG or AI/EPS exists, supply it and the component gets replaced. Raised by Claude Code, 2026-08-26 | Nothing — the mark renders. This is about fidelity, not a blocker |
| **Q23** | **Is a Gitea `act_runner` registered, and are Actions enabled in `app.ini`?** *The version half is closed:* the instance reports **1.27.2** `[verified 2026-08-26 — /api/v1/version]`, so the `vars` context is supported and the first-step guard is belt-and-braces rather than load-bearing. **What remains is not a fact to look up but a dependency on a person:** git.larsnolden.com is **jointly administered**, and both enabling Actions and registering a runner need the second administrator. Until then `npm run deploy` is the path, and it is documented rather than treated as a workaround | How deploys are triggered — not what they do |
## 10. Risks
@@ -379,13 +410,13 @@ never being raised again.
|---|---|---|---|
| R1 | **Licensure.** No site exists yet — `src/pages/` does not exist. **As specified**, the copy will assert the JD only and describe the boutique role as *active litigation exposure*, never *practice*. Pouya flagged that as an interim position and asked to be reminded to change it. §4 now records licence status as `[unestablished]`, which is the honest state, not a resolution | 2026-08-26 | If he is licensed and in good standing, it is the first credential appointing bodies and opposing counsel look for, and its absence from a detailed credentials page is conspicuous. If licensure is in progress, the copy should be rewritten the moment it completes. Either way this is a **temporary** framing that will otherwise ossify |
| R2 | **Matter counts stay off the site until they are independently credible.** Revisit once there is a number a sophisticated GC would find persuasive on its own | 2026-08-26 | §4 forbids them now. That rule has an expiry date nobody has set |
| R3 | **Indigenous engagement practice page.** Deliberately omitted at launch (§6). Revisit at month 1218 | 2026-08-26 | The strategy brief rates it the most valuable single niche. Omission is a timing call, not a permanent one |
| R3 | **The month 1218 practice-area review — now two candidates, not one.** *(a)* **Indigenous engagement**, deliberately omitted at launch (§6). *(b)* **Tax-adjacent disputes**, added 2026-08-26 on the Canadian Tax Foundation membership: it is the one credential none of the six areas touch, and valuation, earn-out, indemnity and shareholder disputes that turn on a tax position are ADR territory. Reasoning for both is in `docs/01-architecture.md`. One review, two candidates | 2026-08-26 | The brief rates the Indigenous niche the most valuable single one, and omission there is a timing call rather than a permanent one. The tax case is the same shape and fails for the same reason today: a practice page is a claim of present capability, and a membership is a credential, not a caseload. Both stop being true at some point, and nothing will tell you when |
| R4 | **Insights cadence.** D9 commits to monthly. A blog that stops is worse than one that never started | 2026-08-26 | The section's whole value is compounding |
| R5 | **Fee review at 12 months.** Published rates are sticky; the right moment to move them is deliberate, not reactive | 2026-08-26 | D14 is priced for where the practice is going, not where it is |
| R6 | **Booking tool.** Parked by Pouya on 2026-08-26; `/contact/` ships with the intake form and a reserved slot for an embed | 2026-08-26 | He asked to be reminded. D10 committed to booking because it removes the back-and-forth that loses appointments — the form alone is a partial answer |
| R9 | **The SES alarms notify nobody until the `ses-alerts` email subscription is confirmed.** `SES-BounceRate-High` and `SES-ComplaintRate-High` are configured and live; the SNS email subscription to `info@smlcompany.ca` is **pending confirmation**, and an unconfirmed subscription drops every message | 2026-08-26 | A monitoring control that exists but does not deliver is worse than none, because it reads as covered. At this volume five bounces can cross the ~5% suspension threshold. Tracked in §7 and on the cutover checklist, but a one-click task nobody owns is exactly what §12 is for |
| R10 | **OBA section membership renews yearly.** §4 verifies Construction & Infrastructure, ADR, and Civil Litigation as of 2026-08-26 — *for now* | 2026-08-26 | A credential that lapses quietly is the failure mode §4 exists to prevent, and OCNI already did exactly this (§4 records it as "not current, do not publish"). Re-confirm at renewal, and before any page listing memberships ships |
| R11 | **Re-check dependency currency at every phase boundary in the build order** (`docs/01-architecture.md` §Build order, 11 steps). Run `npm view <pkg> version` across **every** pin in `package.json` and compare; do not wait for something to break. Verified does not mean latest — record the reason for any deliberate hold in §7 | 2026-08-26 | `astro: "^5.0.0"` was recalled rather than checked and was two majors stale the day it was written, which meant a framework carrying high-severity XSS advisories. Between phases is cheap; after a phase of pages is written is not. The build order has ten more boundaries |
| R10 | **Annually-renewing memberships.** §4 verifies the **OBA sections** (Construction & Infrastructure, ADR, Civil Litigation) and the **Canadian Tax Foundation** as of 2026-08-26 — *for now*. Both renew yearly. *Widened 2026-08-26 when CTF was added; it was OBA-only before* | 2026-08-26 | A credential that lapses quietly is the failure mode §4 exists to prevent, and OCNI already did exactly this (§4 records it as "not current, do not publish"). Re-confirm at each renewal, and before any page listing memberships ships `/about/` at build step 3 is the first one that will |
| R11 | **Re-check dependency currency at every phase boundary in the build order** (`docs/01-architecture.md` §Build order, 11 steps). Run `npm view <pkg> version` across **every** pin in `package.json` and compare; do not wait for something to break. Verified does not mean latest — record the reason for any deliberate hold in §7. **Carries one specific re-add trigger: at step 7, put `@lhci/cli` back.** Check for a patched release — do not assume `0.15.1` is still the ceiling just because it was on 2026-08-26 — pin it against `npm view` that day, write a `lighthouserc` with the budgets from `docs/04-seo-spec.md`, and delete the UNAVAILABLE notices this repo now carries in six places (§7 lists them). If the advisories are still unfixed, that is a decision to take deliberately, not a reason to leave the gap unstated | 2026-08-26 | `astro: "^5.0.0"` was recalled rather than checked and was two majors stale the day it was written, which meant a framework carrying high-severity XSS advisories. Between phases is cheap; after a phase of pages is written is not. The build order has ten more boundaries |
| R12 | **`compressHTML: true` is a deliberate deviation from the Astro 7 default (`'jsx'`).** Measured 2026-08-26: in an `.astro` template an inline pair split across two lines renders as `<em>a</em><strong>b</strong>` under the default — the space is silently deleted. MDX prose is unaffected | 2026-08-26 | It is a deviation, and undocumented deviations become folklore. Revisit **with a measurement**, not a preference — and re-measure after any Astro major, since the behaviour could change again |
| ~~R7~~ | **RATIFIED / SUPERSEDED 2026-08-26.** (a) Cache-policy table matching the pipeline — **accepted**; documenting what the pipeline does beats documenting an intention. (b) `s3:AbortMultipartUpload` omitted — **accepted, reasoning corrected**: the lifecycle rule does not exist and is therefore not the cover; the actual cover is that `aws s3 sync` only goes multipart above 8 MB and the largest asset is a 357 KB portrait. Recorded in `docs/06-deployment.md` with a revisit trigger. (c) The `aws s3 ls` pre-flight — **superseded** by the variable guard now running as the workflow's first step | 2026-08-26 | — |
| ~~R8~~ | **PROMOTED TO A RULE 2026-08-26.** A reminder was too weak for a pattern that survived three entries. *A sweep is a command, not a claim* now sits in `CLAUDE.md` under Conventions, in `/build` Phase 6, and in `/wrap` step 3: any claim that a change was applied across files must cite the command and be written only after reading its output | 2026-08-26 | — |
@@ -394,6 +425,267 @@ never being raised again.
# Change Log
## 2026-08-26 (u) — Build step 1. Zero JavaScript, and both review passes found defects in the first pass's fixes
**Who:** Pouya ruled on CTF, Q30, Q31 and the Lighthouse gap, and set the
direction for step 1. Claude Code implemented under `/build`;
`adversarial-reviewer` and `claims-auditor` each ran **twice**, and the second
pass is where most of this entry comes from.
### What Pouya decided
- **Canadian Tax Foundation membership** added to §4 and to
`CREDENTIALS.memberships`, `[verified 2026-08-26 — Pouya]`, **for now** — it
renews yearly, so **R10 was widened** from "OBA section membership" to
"annually-renewing memberships" covering both.
- **Not a seventh practice area at launch.** CTF is a credential none of the six
areas touch and tax-adjacent disputes are ADR territory, but there is no track
record to point at. Recorded in `docs/01` beside the Indigenous-engagement
omission, and **R3 widened from one candidate to two** — one month 1218
review, two questions.
- **Q31 CLOSED — Plausible**, decided rather than defaulted. Pouya checked and
found his own assumption wrong: Fathom is Canadian-owned but stores non-EU
traffic on US servers, isolating in the EU only for EU visitors; Plausible
holds everything in the EU. **D15 amended** from "Plausible **or** Fathom" to
Plausible, with that reasoning and with Fathom recorded as rejected on data
residency rather than on quality.
- **Q30 CLOSED — SML Company Ltd is incorporated FEDERALLY, under the CBCA.**
Two facts were being conflated and one was wrong: `site.ts` carried
`'SML Company Ltd. · Ontario, Canada'`, which reads as a jurisdiction of
incorporation and named the wrong one. Jurisdiction of incorporation is
federal; place of business is Toronto, Ontario; they are different facts.
**Neither is published** — the footer reads `© <year> SML Company Ltd` and
stops, on Pouya's direction given twice. No corporation number: none is held
and none is needed. §4 carries the caution that "federally incorporated" says
nothing about licensure and nothing about where the practice may operate, and
must not be read together with the **Licence status — NOT ESTABLISHED** row
into an implication neither makes.
- **The Lighthouse gap, ratified and closed as a documented-control problem.**
Removing `@lhci/cli` was right — seven high-severity advisories for a tool
that could not run — but it left `docs/04`, `CLAUDE.md` and `/build` Phase 5
all requiring a check that had silently become impossible. That is Q22's
defect in a different costume. The unavailability is now stated in **six
places**, listed in §7, and `adversarial-reviewer` is told **not** to raise the
absence as a finding. **R11 carries the re-add trigger** for step 7, including
"check for a patched release; do not assume `0.15.1` is still the ceiling".
### What shipped
`src/layouts/BaseLayout.astro`, `src/components/{SEO,SiteHeader,SiteFooter,Button,InfinityMark}.astro`,
`public/fonts/` (six cuts), `public/favicon.{svg,ico}`, `public/apple-touch-icon.png`,
and a temporary proof sheet at `/type-scale/` that step 2 deletes.
**The fonts were never on disk.** `global.css` declared six `@font-face` rules
pointing at `/fonts/*.woff2` and `public/fonts/` did not exist, so every face had
been silently falling back to Georgia and the system sans. The design system had
never once rendered as specified. Six cuts committed, **123,804 bytes** (not the
136 K `du -sh` reports — that is disk blocks, and §7 is read in a performance
context), provenance and SIL OFL licences in `docs/reference/fonts-provenance.md`.
Every URL carries `?v=1` because the deploy script serves `/fonts/*` `immutable`
for a year and no invalidation reaches a browser cache.
**The infinity mark was recoverable, and is not a redrawing.** The deployed site
serves its own loading-thumbnail SVG labelled `smlMark`; `InfinityMark.astro` is
that path verbatim, with the source's `translate(60 0)` folded into the
coordinates. Stroke widths (28/6) and the 0.7 inner opacity are the source's.
Geometry verified to fit its viewBox with 6 units of margin, so it cannot clip at
any size. **Q32 opened** — a loading placeholder is not necessarily the canonical
file, and D7 says the mark carries over *unchanged*.
**The proof sheet computes rather than restates.** It reads `tokens.css` at build
time and runs the WCAG luminance formula over it. All eleven ratios reproduce
`docs/02`'s measured table exactly — 16.81, 11.75, 12.29, 8.95, 5.47, 3.11, 2.10
on cream; 16.81, 11.09, 8.00, 3.07 on ink. It cannot drift from the tokens
because it is derived from them.
**Insights is gated, not hardcoded.** `docs/01` keeps the section out of primary
nav until two pieces are live, so `SiteHeader` reads the collection count at
build time. It does not render today and appears by itself at step 7.
### Decisions taken during implementation
- **ZERO JavaScript, not "minimal".** The reveal was an inline
`IntersectionObserver` in `<head>`. `docs/05` specifies `script-src 'self'`
with no `unsafe-inline` — so the only script on the site was the one thing the
site's own CSP would refuse to execute, and a per-build hash drifts from the
policy pinning it. Replaced with `animation-timeline: view()` behind
`@supports`. **0 `<script>` tags and 0 `.js` files in `dist/`.** `docs/02`
§Motion amended: the `IntersectionObserver` route is now ruled out, not merely
second choice. `docs/05` gained the converse note — inline `style=` attributes
are now load-bearing, so hashing `style-src` would collapse the infinity mark.
- **Header sticky from 64rem, not `docs/02`'s "sticky".** Measured: the one-row
header must hold brand + **seven** nav items + CTA, which it does at 1024px
with 32px clearance and not below. Below 64rem the nav takes its own row and
the header is 137px (tablet) / 185px (phone) — more of a small viewport than a
sticky header is worth. `docs/02` amended with the measured numbers.
- **"Condenses on scroll" is now a rule and a shadow, not a size change.** A
`position: sticky` header stays in normal flow, so shrinking its padding
shortens its layout box at the top of the document and lifts every page below
it — a scroll-linked layout shift on every page, against the CLS < 0.05 budget.
- **`--section-y` corrected.** `6vw + 2rem` reaches its own upper bound only at a
2133px viewport, so the "160px desktop" half of `docs/02` was never delivered
(measured 108.8px at 1280, 128px at 1600). Now `9vw + 1rem` — 160px at 1600px.
- **The measure is opt-in.** A global `p { max-inline-size: 68ch }` capped every
paragraph in every card and footer, forced components to opt back out, and made
`.prose` a class with no effect. Moved onto `.prose`.
- **`robots.txt` disallows nothing.** `Disallow` + `noindex` on the same path
cancel out: a crawler forbidden to fetch a URL never reads the `noindex`. The
legal pages are footer-linked from every page, so the pair would likely have
produced bare-URL listings with the suppressing directive unread. `docs/04`
amended.
### What the reviews found — including in each other's fixes
**Round 1 — code (5 blocking, 7 should-fix).** All fixed and re-measured:
the `animation` shorthand silently collapsed by Lightning CSS (dead in every
production build, alive in dev); a seven-item nav that fit at no width; parent
styles that never reach a child component's root in Astro; gold text shipped at
**1.76:1**; 27 touch targets under 44px; revealed content printing blank; a skip
link landing behind the sticky header; 72px of overflow at 320px masked by
`body { overflow-x: hidden }`.
**Round 1 — claims (FAIL, 8).** The masthead tagline `Mediation · Arbitration ·
Toronto` — never specified for the header, and unqualified `Arbitration` beneath
a name reads as a held capability against §4's Q.Arb row. Removed; **Q33 opened**
for the form the question takes at step 2. A four-stage service timeline and two
unverified assertions about the previous build, both removed from a page that
exists to demonstrate CSS.
**Round 2 found defects in round 1's fixes — four of them.**
1. **The minifier bug was written back into its own fix.** Having just diagnosed
that `animation:` beside `animation-timeline` gets folded into an invalid
declaration, the replacement reveal used the same shorthand. Caught only
because the print test still failed. Both are longhand-only;
**`/build` Phase 5 now greps `dist` for it** and `CLAUDE.md` carries the rule.
2. **The claims fixes were silently lost.** The patch applying all four aborted
on a later assertion *before* writing the file, having already reported four
successes. The service timeline was still in the source and still in the
build.
3. **The colour-alone fix used the banned pairing.** Nav state was given a gold
underline so colour would not carry meaning alone — gold on cream is 2.10:1,
below WCAG 1.4.11's 3:1 for a state indicator, so it carried nothing and the
state reverted to colour alone. Now maroon at 12.29:1, 2px, dotted for section
and solid for current page.
4. **`--header-h` was stamped `[measured]` before anything was measured.** It
said 4.75rem. Actual is **77px** at every sticky width, six items and seven.
5. Plus: a retracted "470 KB PNG" figure surviving in a file written the same
day; two "measured" comments giving 34px and 14px for the same measurement;
`docs/02` amended to a 60rem threshold the code no longer used; flex `order`
putting focus order out of step with visual order between 640 and 1023px.
**Round 2 — claims (FAIL, 10).** The most serious was inside the review
apparatus: **`.claude/agents/claims-auditor.md` said "Memberships. ADRIC, ADRIO,
OBA sections **only**"** — contradicting a §4 that had gained CTF that morning.
It would have flagged a verified membership as unverified and would not have
noticed CTF being dropped. That file has now hosted a stale claim **twice**, so
the list was not updated — it was **removed**, replaced by an instruction to read
the §4 row at audit time. Also fixed: two specs instructing a public phone onto
pages against a §4 row that records none (Q3, answered four entries ago); a
`robots.txt` reproduced inline in `docs/04` that had already drifted; Q.Arb
described as "in progress" where §4 pins "commenced August 2026"; and headline
option 3 struck as asserting party, counsel *and* neutral.
**`ROLE` added to `site.ts`** — there was no constant for *"Director of Firm
Operations"* or *"active litigation exposure"*, the two highest-risk strings on
the site, and both were headed for hand-typing at step 3 and in the `Person`
JSON-LD. `npm run check` then caught a temporal-dead-zone error in that fix.
### Declined, with reasons
- **The nav and footer naming `Arbitration`, `Med-Arb`, `Energy` and
`Shareholder`** — raised on both claims passes. Every one is locked
architecture (D5, §6, `docs/01`), and §4 registers claims about Pouya rather
than enumerating service lines. Removing them is not an implementer's call.
**Opened as Q35** so the judgement is visible rather than missed.
- **Inlining critical CSS.** `docs/04` names it, but the bundle is 22.5 KB
against a 4 KB `inlineStylesheets: 'auto'` threshold; inlining it into all
nineteen pages costs more than the one round trip it saves and destroys
cross-page caching. Revisit at step 11 against real Lighthouse numbers.
- **Simplifying `PRACTICE_SLUGS` / `PRACTICE_AREAS`.** A fair simplicity finding,
but it touches the content schema a prior review round hardened, and rewriting
it as a rider on step 1 is exactly how defects 1 and 2 above happened.
Deferred to its own change before step 7.
- **The sitemap 404.** `<link rel="sitemap">` removed as inert (it is not a
registered link relation and no crawler consumes it); the `robots.txt`
`Sitemap:` line resolves at step 2. **Step 1 is not deployed** — no deploy
credential exists (Q22) and deploys are manual.
- **Second-person copy on the proof sheet.** `docs/03` bars it on counsel-facing
pages; an internal proof sheet is not one, and the page is deleted at step 2.
### Verification — run, not asserted
`npm run check` 0/0/0 · `npm run lint` clean · `npm run build` 0 errors ·
`npm audit` **0 vulnerabilities** · **R11 dependency sweep: 13 of 14 pins at
registry `latest`**, the only drift being the deliberate `typescript` hold.
Measured in headless Chrome across 320/375/640/768/900/1000/1023/1024/1100/1200/1280/1440/1600,
**with a seventh nav item injected** to test the step-7 state that does not exist yet:
- Header **77px, one row, sticky** at every width ≥1024 with six items and seven;
137px static below; **0 overflow at every width including 320px**
- **0 tap targets under 44×44** at any width
- **0 focus-order inversions** (`checkVisibility`-filtered); closed `<details>`
panels contribute **0** hidden tab stops
- State indicators **12.29:1**; `--section-y` reaches exactly **160px at 1600px**
- `scroll-padding-top` computes to **93px** = 77 + 16, matching `--header-h`
- **0 `<script>` tags, 0 `.js` files**; both scroll-driven animations attach live
(`header-lift`/`scroll()`, `reveal-in`/`view()`)
- Printed to PDF: all four revealed cards present (they were absent before the
print override)
- **755 words** of body text from `curl` with no JavaScript — the old site
returns three
### Sweeps — the commands, not the claims (R8)
```
$ grep -rE 'animation:[^;}]*(scroll\(\)|view\(\))' dist --include='*.css'
(no output)
$ grep -rn "OBA sections only" . --exclude-dir={node_modules,.git,dist,.astro}
.claude/agents/claims-auditor.md:58:enumerate "ADRIC, ADRIO, OBA sections only"; the Canadian Tax Foundation was
(the sole hit is the note recording its removal)
$ grep -c '<script' dist/type-scale/index.html -> 0
$ find dist -name '*.js' | wc -l -> 0
$ grep -c "Mediation · Arbitration · Toronto" dist/type-scale/index.html -> 0
```
The `470 KB` sweep is the one worth recording as a near-miss: after retracting
the figure from `docs/02`, `grep -rn "470 KB"` found it **still asserted in
`src/components/InfinityMark.astro`, a file written the same day**. Without the
grep this entry would have claimed a completed retraction. Three previous entries
made exactly that mistake.
### Questions
**Closed:** Q30 (federal, CBCA), Q31 (Plausible).
**Opened:** **Q32** (canonical vector for the infinity mark) · **Q33** (how
arbitration is described in one-line site-wide copy before Q.Arb) · **Q34**
(whether §2's measurements of the previous build still hold — a re-fetch found
zero `base64,` occurrences, but the real application is in nine unfetched
bundles, so this is a question and not a correction; §2 now carries the caveat
inline, and `CLAUDE.md`, `docs/02` and `adversarial-reviewer.md` all cite it
where they quote the figure) · **Q35** (may the nav name a service the register
does not establish) · **Q36** (is co-arbitration work available now — asserted in
three specs, in no §4 row) · **Q37** (is "Law and engineering" the right label
under `JD + ML`).
**§12:** R3 widened to two candidates, R10 widened to all annually-renewing
memberships, R11 given the `@lhci/cli` re-add trigger. **R1 remains live and was
surfaced** — nothing in this change describes Pouya as licensed or as a legal
professional, and the header tagline that triggered Q33 is verified absent from
`dist`.
### Commit shape
Split in two on `adversarial-reviewer`'s own recommendation: instructions that
narrow a reviewer's scope should not travel in the same commit as the work that
reviewer is checking. The `.claude/` changes go in their own `chore:` commit so
the narrowing reads as a decision rather than as a line in a feature diff.
---
## 2026-08-26 (t) — Astro 5 → 7. The review found a defect in the fix, twice
**Who:** Pouya approved the upgrade and set the version-pin rule. Claude Code