Dossiers

Dossier evidence rules (hard rule, no exceptions)

Every claim links to the exact public page or video moment. Evidence rules

Dossier evidence rules (hard rule, no exceptions)

Set by Justin Smith on 2026-10-11. Applies to every dossier in dossiers/ and to anything the site says about a named person.

The rule

Every claim about a person carries a public link to the exact evidence for it. "Exact" means a reader who clicks lands on the statement, vote, or page itself: the right page of the PDF, the right second of the video, the right agenda item. A link to a site's home page or a meeting list is not evidence.

What each kind of claim links to

Claim type Required evidence link Label
Vote / motion / outcome (minutes exist) Approved minutes PDF at the page: MinutesViewer…#page=N none needed (official record)
Vote / outcome (minutes not out yet) Granicus video at the moment of the vote: MediaPlayer…&entrytime=S "machine transcript, unofficial; replace with minutes when approved"
Sponsorship / authorship Docket/agenda PDF at the page with the BY: line or the signed letter: AgendaViewer…#page=N none
Quote from a document The PDF page (#page=N) or web page (optionally with a #:~:text= fragment) where the words appear none; must be verbatim, [sic] for errors
Paraphrase from minutes The minutes page (#page=N) [paraphrase from minutes]
Quote from a meeting video Video at the timestamp (&entrytime=S or YouTube &t=Ss) "machine transcript; check against the video" (wording is ASR)
Machine speaker attribution (who said it) Video at the timestamp of the remark plus a link to the moment that identifies the voice (for example, the chair being addressed by name) "Speaker identified automatically by voice matching, not by official record"
School board vote BoardDocs item link (shows "Motion & Voting" with mover, seconder, Yea/Nay by name) none
Self-description (bio, questionnaire, campaign site) The page, ideally with a #:~:text= fragment "her/his own description, not independently verified"
Secondary source (news) The article URL "secondary source"
Election result Cuyahoga BOE certified results PDF at the page "unofficial" if it is not the certified canvass

Verified link formats (tested 2026-10-11 ET)

Source Format How it was verified Status
Granicus video at a timestamp https://onelakewood.granicus.com/MediaPlayer.php?view_id=2&clip_id=<clip>&entrytime=<seconds> Clip 3165: HTTP 200 (redirects to /player/clip/3165?view_id=2&entrytime=720). The server writes the value into the player config (start_time: 720; start_time: 0 without it), and Granicus's own share/embed code builds links with &entrytime=. Player chapter cuepoints (13:52 item 3, 14:08 item 4) line up with our ASR times (13:52, 14:10), so ASR seconds = player seconds for Granicus clips. Works. Caveat: actual playback couldn't be watched from the box (the video CDN refuses the box's headless browser), so the seek itself was confirmed from the player config, not on screen.
Granicus minutes PDF at a page https://onelakewood.granicus.com/MinutesViewer.php?view_id=2&clip_id=<clip>&doc_id=<uuid>#page=<N> 200, 302 → DocumentViewer.php?file=…pdf, application/pdf, served inline (no attachment header). Browsers keep the #page fragment across the redirect. N is the PDF page index; for Lakewood minutes it equals the printed page number. Works in Chrome, Edge, Firefox, desktop Safari. iOS/Android viewers may ignore #page, so always also write "p. N" in the text.
Granicus agenda/docket PDF at a page https://onelakewood.granicus.com/AgendaViewer.php?view_id=2&clip_id=<clip>#page=<N> (or &event_id=<id> before a video exists) Same as minutes. N ≠ the docket's printed "pg.": Oct 5 and Sept 8 dockets have 3 cover pages, so PDF page = printed page + 3 (printed pg. 161 = #page=164). Always compute N from the PDF itself. Works (same caveat)
BoardDocs agenda item https://go.boarddocs.com/oh/lwcsoh/Board.nsf/goto?open&id=<ITEM_UNIQUE> (item ids from BD-GetAgenda); meeting: same with the meeting id goto?open&id=DXWL925545A1 loaded in a real browser shows "Agenda Item Details … Motion & Voting … Motion by Lisa Dopman, second by Nora Katzenberger … Yea: …". 200 with a browser User-Agent. Works
YouTube at a timestamp https://www.youtube.com/watch?v=<id>&t=<seconds>s Video id w4HUbUbaYdE confirmed public via YouTube oEmbed (200, title "09-28-2026 Lakewood City Schools Board of Education Meeting"). &t= is YouTube's standard start-time parameter. Use it, but the box can't load the watch page itself (YouTube returns 429/"sorry"), so the link checker verifies the id via oEmbed, not the seek. YouTube auto-caption timing matches the video timeline.
City / other web page Plain URL; for a quote, optionally add a text fragment #:~:text=<exact words> lakewoodoh.gov/city-council/sarah-kepple/ etc. 200; quoted text confirmed in the fetched HTML. Works. Text fragments highlight in Chrome/Edge/Safari and Firefox 131+; older browsers just open the page, so the quote must also be in the dossier text.
Cuyahoga BOE results PDF https://boe.cuyahogacounty.gov/elections/GetDocumentById/<uuid>/#page=<N> Certified "NOV25GEN – Official Results by Contest" (2025-11-19): 200 application/pdf; Lakewood Council at Large is on PDF page 17. Works

Formats that did NOT work or must not be used

Procedure for every new or updated claim

  1. Find the public document or video moment. Compute #page=N from the PDF itself (pdftotext + search), or the second from the ASR segment start (link about 2 s early).
  2. Put the link on the same line as the claim, with the label from the table above.
  3. Run python3 tools/check_dossier_links.py dossiers/<name>.md. Every link must return 200, and every claim line needs a link.
  4. When minutes are approved, swap machine-transcript links for minutes links and drop the label.
  5. When something can't be linked, move it to "Unverified / pending public source" as a question, or delete it.