Commit Graph
4 Commits
Author SHA1 Message Date
Pouya LajevardiandClaude Opus 5 02739adac9 fix: refute (ar)'s intake finding; fix the D20 gloss class; add X-Robots-Tag on *.pdf
Build and deploy / build-and-deploy (push) Failing after 4s
Pouya's rulings of 2026-09-03, in five parts.

1. THE INTAKE FORM IS NOT BROKEN. (ar) was wrong. docs/09 §7.1 verbatim —
POST /api/intake with an Origin header — returns 303 to /contact/could-not-send/
with access-control-allow-origin echoed; the same probe without Origin returns
403. A bare POST 403s BY DESIGN and §7.1 says so three lines below the probe it
prescribes: "403 means the Origin header did not arrive". The earlier finding
read a status code without reading the document that defines it. Second time in
two days. CLAUDE.md's instrument list goes eight to nine. D20 findings 12 and 19
fall with it; §7.2 (that both emails arrive) is still owed.

The correction is APPENDED as entry (as); (ar) stands unedited.

2. The privacy retention comment was stale, not a defect — superseded by his
decision to publish and confirm after launch, reading from 2026-09-04. Reworded;
the TODO(pouya) came off with the gate it enforced. The mechanism finding
survives: it was a JSX comment, stripped by Astro, so no build or deploy path
could see it. A publication gate that lives only in a stripped comment is not a
gate. §9 Q60 corrected.

3. The gloss class is fixed — 15 of the 20 D20 findings, 14 distinct edits across
9 files, under the rule "the gloss may say no more than the extract says; no new
claims, no new sources". Swept three unpublished insights drafts too, and
corrected the wrong CAA attribution at its source in docs/reference/, which is
where a fixed page re-seeds. /bio/ changed, so the committed PDF is regenerated
(89,549 B, 1 page asserted). Three findings outstanding: 10 needs a ruling, 11 is
ruled and owed via Q60, 13 needs him to have said it. R1 is not one of the twenty.

4. X-Robots-Tag cannot be done with S3 object metadata — --metadata writes user
metadata, returned as x-amz-meta-x-robots-tag, which no crawler reads. Built as
the CloudFront response-headers policy docs/06 has specified all along:
configure.mjs section 4. It needs a --apply run, not a deploy. The policy is
cloned from whatever is attached at run time and reconciled on every run, because
a response-headers policy replaces rather than merges.

5. Headshot deferred as an open non-defect. The master and the srcset ladder are
both fine; Astro passes no quality, so AVIF encodes at sharp's default 50 and is
served first.

Two review rounds, 29 findings, all resolved, none declined; stopped at two per
D19. NINE of round 2's fourteen were defects in round 1's own repairs — including
a fix that harmonised both /fees/ rows onto wording that was itself unregistered,
publishing an unsourced fee term twice where it had been once.

Gates, exit status read for each: check 0 (0 errors, 0 warnings, 0 hints),
build 0 (23 pages), check:claims 0, check:intake 0, og:proof 0, lint 0, minifier
grep exit 1, router.test.mjs 30/30. Lighthouse NOT run. Nothing deployed and
nothing applied to the distribution.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
2026-09-03 17:23:20 -04:00
Pouya LajevardiandClaude Opus 5 fce89d46eb fix: header reflows under enlarged text; reopen the step-1 nowrap decision
The step-1 header decision is formally reopened (AGENTS.md (ak)): its record
attributed the residual to the wrong cause and read a measured 944px functional
failure as a robustness margin.

Mechanism — wrapping, plus a gated sticky offset:
- `flex-wrap: nowrap` removed from `.header-inner` (measured necessary AND
  sufficient) and from `.nav-list` (measured inert; removed so the prohibition
  is not contradicted by a `nowrap` in the same file), with a dead `flex: none`.
- `inset-block-start` becomes a two-band, two-term saturating clamp() so the
  header is sticky only while the masthead is one row. A media query cannot
  express this: its `rem` resolves against the browser DEFAULT font size, a
  property's against the root element. The second term catches a root BELOW the
  default, where the 80rem content cap shrinks faster than the header's px
  minimums; without it 65px of `#main` sat behind the header at 9px.
- Wrapping is the only mechanism that reflows under all THREE enlargement paths,
  because Chrome's minimum-font-size setting is invisible to @media, to
  @container and to every length unit.

Measured, 22 pages x 16 widths = 352 page-widths per method:
  root-style 32px        175/352 -> 0/352   (1280px: 944px overflow -> 0)
  minimum-font-size 32   219/352 -> 88/352  (residual is the footer email)
  default-font-size 32     0/352 -> 0/352
  default (root 16)        0/352 -> 0/352
Nav items and CTA on-screen in 1408/1408. A further 762 points across roots
9-32, both thresholds, the band seam and all five Chrome presets: 0 failing.

Normal-settings identity: 0 differences on 352 page-widths across six metrics,
with six nav items and with a seventh injected. Header 81.00px at all eight
widths >= 1056, CTA gap 0.00px. Lighthouse: 22 pages, no category below 95,
CLS 0.000 on every page.

--header-h is reworded as a FLOOR, not a constant; value unchanged.

Also in this step, per ruling:
- /bio/ print `font-weight` frozen at 400 — the circulated PDF's typography
  changes only when its content is deliberately revised, never as a side effect
  of a screen refactor. Declaration byte-identical; the constraint is recorded.
- CLAUDE.md: the two-simulation rule for enlarged text, the zsh
  no-word-splitting rule, the third (minimum-font-size) mechanism, and
  "state the grid with the count".

Two rounds of adversarial-reviewer, eleven findings, all resolved; round 2's
blocking finding was a defect in round 1's own fix. Two suggested fixes declined
with reasons in (ak). claims-auditor deliberately not run — D20.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
2026-09-01 12:34:50 -04:00
Pouya LajevardiandClaude Opus 5 0f7595b602 feat: eyebrow 14px and one small-text floor; fix a site-wide reflow defect; stamp TTL; §4 bars the struck universal
Pouya's five rulings of 2026-08-31, after 64bce10. One commit, because AGENTS.md
entry (aj) covers all five and the review fixes interleave across them —
recorded here rather than left to be inferred.

1. THE EYEBROW, 13 -> 14px, at the one token definition. `--text-eyebrow` is
deliberately NOT an alias of `--text-sm` despite sharing its value: the two move
for different reasons, and aliasing would mean a change to body-meta type
silently moving every eyebrow. Sweep by rendering, 22 pages x 2 widths, 801 mono
instances: 441 carry `.eyebrow`, 420 now at 14px, 21 held at 11px. Zero of 801
below 4.5:1.

Header check, which Pouya asked for explicitly: nothing header-side consumes the
token, `--header-h` is 81px, and the sticky header measures exactly 81.00px at
every width from 66rem up with the CTA on `.header-inner`'s content edge. Nothing
overflowed, so nothing was improvised.

2. /contact/'s LABELS RAISED, AND THE FLOOR CLAIM REWRITTEN BECAUSE THE RULING'S
PREMISE WAS FALSE. The ruling asked docs/02 to record the tagline as "the ONLY
sub-14px text on the site". It is not: the `--text-xs` 12px rung has ten
declaration sites and 130 elements rendering at 12px. So docs/02 records the
claim that IS verified — `--text-2xs` has one consumer in the repository — and
enumerates the 12px rung as a separate treatment. Writing a false claim into the
spec because the conclusion was handed down is the move the rules forbid.

A third block moved that the ruling did not name: /bio/'s ten <h2>s and its strap
were copies of five of `.eyebrow`'s six declarations at 11px — the same escape the
footer headings were. docs/02 justified holding them by the one-page PDF
constraint; measured, `@media print` sets both to 7pt, so the screen size never
reached the PDF and that was never the reason.

Consolidating them DID change the printed sheet, because the missing sixth
declaration was `font-weight`: 500 grew the PDF 89,496 -> 91,151 bytes. Print
therefore freezes 400, the committed PDF stays byte-identical (10 differing
bytes, all /CreationDate and /ModDate), and unifying is Pouya's call.

3. THE REFLOW DEFECT WAS SITE-WIDE AND /bio/ WAS NOT THE BINDING CAUSE.
`white-space: nowrap` on `SiteHeader .brand-name` held all 22 pages 63px over at
320px/root 32. Eight cause-specific fixes, no `overflow-x` anywhere; all eight
produce byte-identical geometry at root 16. `Pill` is marked in docs/02 as the
backstop it is — the real cause was `PracticeCard`'s rem-based padding, and with
it clamped "Construction" goes from 94x220 in six two-character lines to 158x85 in
two.

Three instrument findings now in docs/02, each of which hid a real defect:
`break-word` does not reduce min-content and `anywhere` does;
`getBoundingClientRect()` reports border boxes, so an element sweep cannot see
text spilling outside its own box; and `mobile: true` emulation expands the
layout viewport, so `scrollWidth - innerWidth` reads 0 while the reader still
scrolls sideways.

4. TTL STAMPED `ENABLED` in §7, with `DISABLED` at first verification recorded
rather than overwritten. Q60 narrowed to its second half and OPEN: no record has
been watched to vanish, and `ENABLED` proves the setting, not the behaviour.
R19's sweep found three stale copies outside §7; all now defer to it. R19 itself
was not edited — it points at §7 rather than carrying state, which is the
property that made it work.

5. §4 GAINS THE STRUCK-UNIVERSAL ROW, citing the committed ontario.ca extract and
cross-referenced to `check:claims`'s `struck-universal-q39`. It bars the claim in
BOTH directions: the commercial half is Pouya's attributed position, not a
verified fact. The row immediately caught two places asserting it flatly —
`SiteHeader.astro` and §9 Q33 — both now attributed. `check:claims` unmodified;
still frozen.

REVIEW: adversarial-reviewer, two rounds, 16 findings, ALL ACCEPTED, NONE
DECLINED. claims-auditor did not run (D20). Eight of round 2's ten were defects
in round 1's own fixes.

Round 1's blocking finding was a defect in my own record: I wrote that every
reflow residual was zero at "root 16 and root 32, 286 measurements". Two ways of
simulating 200% text are NOT equivalent, because media-query `rem` resolves
against the DEFAULT font size, not the root element's. Under the method docs/02
itself prescribes the site is 944px over on 21 pages and 508px on / at 1280, and
304px at 1920 — nav clipped mid-word, Practice/Fees/Contact and the CTA
off-screen, WCAG 1.4.4 with loss of functionality. My 286 excluded exactly the
widths where the defect lives.

NOT FIXED, DELIBERATELY: the cause is `flex-wrap: nowrap` on `.nav-list` above
66rem, a locked step-1 decision, and the standing instruction is to stop and
report rather than improvise a header change. It is now a blocking item on
docs/06's cutover checklist, ticked only by ruling on it — "not by re-measuring
it with the method that reports zero".

Round 2 also caught: a 63,743-byte figure that was the `cmp -l` differing-byte
count rather than the 1,655-byte size delta; a lost-navigation list naming
Med-Arb, which is not in the masthead at any width, while omitting Contact; the
tagline's justification left recorded at 13px, where one clause of it is false at
14px (20px of document overflow at 1216 with a seventh nav item); my own label
raise reintroducing a 38px element overflow at the width just ruled on; two
copies of the eyebrow treatment left at weight 400; three stale residual tables;
and the min-content explanation duplicated six times in src/.

VERIFIED, exit statuses read directly, never through a pipe: build 0 (22 pages),
check 0 (0 errors/0 warnings/0 hints), check:claims 0, og:proof 0, check:intake 0,
lint 0, minifier tripwire clean, TODO in dist 0 with a source sanity check.
Overflow: 374 measurements over 22 pages, every one zero, row counts asserted
before reading, with positive controls (119px at width 200, 319px at root 64).
Lighthouse 0, run three times with identical category scores: perf 99 on / and
100 elsewhere, a11y 100, best practices 100, SEO 100 on all indexable pages,
CLS 0.000. / sits at LCP 2.03s against a 2.0s budget, unchanged by this work.

The zsh `$VAR` word-split trap fired twice more and both times read as a clean
pass; caught only by asserting row counts first. Two of my own instruments were
wrong before they were right: a `grep -F '0.875rem'` state check that could never
match because Lightning CSS writes `.875rem`, and a probe whose inline
`!important` was outranked by a running CSS transition.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
2026-08-31 15:44:13 -04:00
Pouya LajevardiandClaude Opus 5 210bc25a26 feat: build steps 7a-10 — the site is complete and reviewable at 22 pages
Steps 7a through 10 as one authorised run. Nothing deployed (D11).

7a  Lighthouse returns as `lighthouse@13.4.1` + `chrome-launcher`, NOT
    `@lhci/cli`. AGENTS.md §7's advisory attribution was wrong: the carriers
    were @lhci/cli's own `tmp` and @puppeteer/browsers' `extract-zip`, not
    Lighthouse, which audits clean. A deliberate deviation from R11's literal
    trigger, recorded with what it costs. Local gate; CI has no Chrome.

7b  OG card generator (satori + sharp) discharges R15 — 20 typed cards plus
    per-article cards; the portrait stays on / and /about/ by Q40. Insights
    plumbing: ArticleCard, Prose, the index, the article route, articleGraph,
    and /'s section 7. Card copy is constrained structurally because text in a
    JPEG cannot be grepped by check:claims: every headline IS its page's <h1>,
    enforced by `npm run og:proof`.

7c  Five drafted launch articles, draft: true / reviewedByPouya: false. An
    independent compliance audit returned 76 findings and 57 unsourced
    assertions; all blocking and should-fix applied.

8   /contact/, the intake form, and backend/intake/ (undeployed). Plain HTML
    POST to a same-origin /api/intake with a 303 redirect, so the form works
    with zero JavaScript. docs/05 records three deliberate deviations.

9   /fees/ on Q59's ruling — overtime runs from the session cap, and the
    reservation point ships adjacent to the rate. One-page PDF bio discharges
    R16; /bio/ is its source, so the circulated artefact stays inside the
    review apparatus.

10  /legal/privacy/ and /legal/terms/, written to the backend as built. Three
    of the policy's statements are derived and cannot drift.

Also: /about/'s inverse credentials band (approved at step 6); Q59 closed;
R15 and R16 discharged; and a fix to shipped copy — /practice/energy/ asserted
the absence of a regulation the source extract says must not be asserted.

Review: adversarial-reviewer, two rounds (D20/D19). Round 1 returned 16
findings including two blocking — an invisible ghost button on /fees/ at
1.00:1 that Lighthouse scored 100, and a privacy policy that named one data
processor when there are two. All 16 acted on.

Lighthouse, 22 pages, mobile: performance 99-100, accessibility 100,
best practices 100, SEO 100 on every indexable page, CLS 0.000.

AGENTS.md entry (ah) has the detail, including four of my own verification
commands that were wrong and what each of them nearly caused.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
2026-08-31 10:56:54 -04:00