# Deviations — PPN World Research Paper No. 2

Every departure from the registration (`paper-2-press-release-anatomy.md`,
commit 4b769927, and Addendum 1), dated, with its reason and its effect.

## Deviation 1 — 2026-10-12, during the census: measuring in parallel (no effect on any measure)

**What.** `measure-pool.mjs` ran one measuring worker; the run was restarted
at 10:15 UTC with three (`MEASURE_WORKERS=3`) and with 40 websites fetched at a
time instead of 16 (`CONCURRENCY=40`).

**Why.** After 22 hours, 39% of the frame was read: every website waited for
its pages to be measured in the single worker's queue (the largest distributor
was fetched at one page every five seconds, against the registered one per
second), and 1,135 small websites had not started.

**What did not change.** The courtesy rules of §4 — one request at a time per
website, at least 1 s apart or the robots.txt `Crawl-delay` — and every
measure. Re-measuring pilot 2's 1,001 pages with three workers gave results
identical, byte for byte, to one worker (1,001 of 1,001 rows). The run resumed
from its log: 96,318 releases already recorded, every line valid, none
duplicated; the pages in flight when it stopped were fetched again.

**Correction, 2026-10-13.** The reason given above is incomplete. The
research computer's power log (Deviation 3) shows it asleep for 17.2 of the
first run's 21.8 hours: it was on battery with its lid closed, and
`caffeinate -i` prevents idle sleep, not lid-closed sleep. While awake, the
first run fetched about 272 releases a minute; the slow progress was mostly the
sleep, not the single measuring worker. The change is kept — it has no effect
on any measure, as verified above — but it did not have the cause stated.

## Deviation 2 — 2026-10-12, 16:13 UTC: one slower retry for "429 Too Many Requests"

**What.** The registration retries a refused page once, at once, as a browser.
A 429 asks the client to slow down, so the 3,046 releases the census recorded
as refused with 429 (on 9 websites; 1,964 of them on one football league's
site) are fetched once more by the same procedure — robots.txt read again,
identified client first, browser once, rendering and measures unchanged — with
at least 30 s between the starts of two requests to a website
(`RETRY_429=1`). The 9 websites run side by side, each one request at a time;
none of them was still being read by the census. Outcomes go to
`retry-429.jsonl`; the census log is not changed.

**Why** and **effect.** Started while the census finished its last four
websites, because the 30 s pace makes the retry long (about 16 hours for the
largest website). Both counts are reported: the registered one (429 = not
fetched), on which the hypotheses are decided, and the one after the retry, as
a robustness count.

## Deviation 3 — 2026-10-13: releases lost to the research computer's sleep

**What.** The computer's power log (`pmset -g log`) shows it asleep for 28.0
hours, in 137 intervals, between the census's start (11 October, 12:19 UTC)
and 13 October, 07:24 UTC. A request in flight when it fell asleep or woke
failed with a network error (a timeout, a DNS failure) — a failure of the
research computer, not an answer of the website — and a page being rendered
failed the same way. The releases recorded as *not fetched* with a network
error and no HTTP status, or whose rendering failed, between 30 s before a
sleep and 60 s after the wake that ended it, are fetched once more by the
registered procedure, after the census. Their first records are kept,
unchanged, in `fetched-sleep-failures.jsonl` (and
`retry-429-sleep-failures.jsonl` for the 429 retry), and the new fetch takes
their place in the log. Network errors outside these windows are kept as
recorded. The power log extract is deposited with the data.

**Why.** The registration counts a release that its website did not serve as
not fetched. These releases were never asked for by an awake computer; leaving
them out would report a property of our computer as one of the websites.

**Effect.** Both counts are reported: the census with these releases as first
recorded, and with their new fetch, on which the hypotheses are decided.
The windows held 1,175 releases of the census log on 21 websites: 1,140
recorded as not fetched with a network error, and 35 whose rendering failed
(recorded as too short, 34, and as having no article, 1). Fetched again on
13 October, 10:41–10:52 UTC, with the computer awake and on mains power: 946
measured, 101 walled, 61 too short, 33 not fetched, 14 with a title that did
not match, 13 not in English, 4 with robots.txt unreachable (all on one
website) and 3 pdf-only. None of the 33 failed with a network error; each had
an HTTP answer (404, 21; 403, 11; 400, 1). The census log then holds an
outcome for each of the 246,777 releases of the frame, none twice. From the
census's last hours on, the computer is kept on mains power with its lid open.

## Deviation 4 — 2026-10-15: a shorter hand check by coder B

**What.** Coder B (the author) codes the first 20 of the 50 releases
registered for coder B, and four of the codebook's twelve questions: dateline
(Q2), contact with email or phone (Q6), an executive quoted (Q11, asked on its
own: an eight-word quotation with a speech verb attributed to a corporate
title) and an emotion word in that quotation (Q12). Each question's rule is
shown under it. The page is built by `5-coding-form.mjs` with `SHORT=1`.

**Why.** The registered form (50 releases × 12 questions) was declined by the
coder as too long to complete. These four questions are the measures
hypotheses H2–H4 rest on; H1 (length) is a word count with no coded judgment.

**Effect.** Coder A's 200 codings on all twelve questions, and the
detector–coder A rule (agreement ≥ 90%, α ≥ .800), are unchanged. A–B α is
computed on 20 releases for the four measures only, with correspondingly
wider uncertainty; for the eight other measures it does not exist and they
decide on the detector–A rule alone (`abRule: false` in reliability.json).
Decided before any coder B answer was read.

## Deviation 5 — 2026-10-15: pages that are not releases, contacts and executive titles read again, a second validation draw

Written after the registered reliability step was run on coder A's 200 and
after `3-analyze.mjs` was run once on the census as registered; that run is
kept and reported beside the revised one.

**Coder B.** Coder B stopped after five releases (two of them partly coded);
Deviation 4's 20 were not completed. No A–B agreement is computed. Coder A is
the only human-role coder and is a language model; the paper says so where
reliability is reported.

**What the registered validation showed.** Detector–coder A on the 200:
dateline, *About*, *For immediate release* and quotation pass the rule
(agreement ≥ 90%, α ≥ .800); contact block does not (83.5%, α .642, recall
.625), executive quotation does not by a hair (91.5%, α .797, recall .773),
emotion word in an executive's quotation does not (95.5%, α .666, recall
.526). Coder A's notes give the causes: the extraction program (Readability)
leaves out the contact block that many websites print beside or under the
text (GlobeNewswire's "Contact Data", the RCMP's and Canada.ca's "Contacts",
sidebars of BLM and pressportal.co.za); titles written in lower case
("managing director", "president and CEO of …") were not read as titles;
quotation marks were paired across paragraphs on pages with straight quotes;
a speaker titled once ("Brian Cameron, Chief Commercial Officer") and quoted
later by surname alone was not linked to the title. Two of coder B's flagged
pages, and four of coder A's eight "wrong" extractions, were GOV.UK pages that
are not press releases.

**What changes.**
1. *Frame.* GOV.UK pages outside `/government/news/` (statistics notices,
   statistical data sets, publications, consultations, speeches, case studies,
   calls for evidence, organisation pages) are excluded as not releases
   (`frame.mjs`), and counted.
2. *Contact block.* When the extracted text holds no contact block, the
   archived page is searched outside its navigation, header, footer and
   cookie/newsletter elements for the same cue followed within four blocks
   by an email address or a phone number. The cue list adds "please
   contact" and "Contact Data/Information/Details".
3. *Executive quotation.* Titles are matched in any letter case (except
   Partner, Owner and Head of, which are ordinary words in lower case); EVP
   and SVP are added; quotation marks are paired within a paragraph; a
   quotation whose speaker is named by surname is linked to the title written
   beside that person's full name elsewhere in the release; a blockquote after
   "… said:" is a quotation.
4. *Second validation draw.* The changes are developed on the first 200
   (now a development set). They are tested once, unchanged afterwards, on a
   new random draw of 100 measured releases (seed 20261015; not among the
   first 200; at least 30 from distributors and 30 from public bodies),
   coded blind by coder A with the same codebook and instructions. The
   registered rule decides which measures may decide a hypothesis, applied to
   the 100. The census is re-measured with the changed detector
   (`2b-remeasure.mjs`) and analysed by the registered `3-analyze.mjs`;
   hypotheses, weights, tests and thresholds are unchanged.

**Reported.** Both counts — as registered and as revised — for every
hypothesis, with the reliability of each.

**Result of the second draw (2026-10-15, recorded before the revised census
was read).** Coder A coded the 100 blind (four sessions of 25; 100 merged,
every answer valid). Detector–coder A on the 100, as registered → revised
detector:

| Measure | Registered: agreement, α | Revised: agreement, α | Decides (revised) |
|---|---|---|---|
| Dateline (H2) | 87.0%, .739 | 87.0%, .739 (unchanged) | no |
| Contact block (H3) | 74.0%, .481 | 89.0%, .779 | no |
| Executive quotation (H4) | 94.0%, .860 | 96.0%, .910 | yes |
| Emotion word in it (H4) | 98.0%, .847 | 99.0%, .928 | yes |
| Quotation | 96.0%, .920 | 97.0%, .940 | yes |
| *About* | 91.0%, .811 | 91.0%, .811 | yes |
| *For immediate release* | 100%, 1.000 | 100%, 1.000 | yes |

Extraction "whole" (coder A): 78%. The contact block improved but stays
under the rule (recall .845), and the dateline, unchanged, passed on the
first 200 (90.5%, .810) and fails on the second (pooled 300: 89.3%). As the
deviation states, the rule is applied to the 100: H2 and H3 are reported
with their estimates and the reliability that keeps them from being
decided; H1 (word count) and H4 are decided.
