User Tools

Site Tools


provenance:design:connected_tv

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
provenance:design:connected_tv [2026/09/12 17:29] – New provenance page for design:connected_tv: inclusion rule, two-gate candidate pool, full verdict map for all 103 audited papers, 191-name fold residue, 33-quote check against .cols and PDF, external source verification, judgement calls. Authored by Clau karel.kubicek.claudeprovenance:design:connected_tv [2026/09/13 02:30] (current) – Quote check: eight needles added for the claims round 2 changed (41 quotes, 0 NOTFOUND); re-embed the checker and its output; section 7 counts and the new-needle table. Authored by Claude karel.kubicek.claude
Line 7: Line 7:
 ===== 1. Why this page exists, and what it is not ===== ===== 1. Why this page exists, and what it is not =====
  
-[[roadmap]] queued ''design:connected_tv'' on 2026-09-07 with a 16-paper candidate set from ''scripts/gap_probe_roadmap.mjs'' (family ''ctv_streaming''), and [[provenance:roadmap]] §5 recorded a condition on it: //"[[Design:Connected TV]] will need its population derived from platform fields rather than the probe, because the probe's ''web''-platform column is exactly the wrong filter for it."// That condition was honoured, and it turned out to understate the problem in one direction and overstate it in another.+[[:roadmap]] queued ''design:connected_tv'' on 2026-09-07 with a 16-paper candidate set from ''scripts/gap_probe_roadmap.mjs'' (family ''ctv_streaming''), and [[provenance:roadmap]] §5 recorded a condition on it: //"[[Design:Connected TV]] will need its population derived from platform fields rather than the probe, because the probe's ''web''-platform column is exactly the wrong filter for it."// That condition was honoured, and it turned out to understate the problem in one direction and overstate it in another.
  
   * **The title probe's precision is 62.5%** — 10 of its 16 are in the final population.   * **The title probe's precision is 62.5%** — 10 of its 16 are in the final population.
Line 44: Line 44:
 | Q10 | ''population[].unit'' | the 35 | ''iot-devices'' 20, ''other'' 17, ''mobile-apps'' 5 | | Q10 | ''population[].unit'' | the 35 | ''iot-devices'' 20, ''other'' 17, ''mobile-apps'' 5 |
 | Q11 | Named instruments, alias-folded, ''used'' only | the 35 | Wireshark 10, tcpdump 9, mitmproxy 4, Frida 3, adb 3 | | Q11 | Named instruments, alias-folded, ''used'' only | the 35 | Wireshark 10, tcpdump 9, mitmproxy 4, Frida 3, adb 3 |
-| Q12 | Interception-evidence probes | 13 Tier A / 35 A+B | router/AP 11/30, mitm 10/22, DNS 5/12, HDMI 6/9, remote-control 12/16, **undecryptable reported 1/1** |+| Q12 | Interception-evidence probes | 13 Tier A / 35 A+B | router/AP 11/30, mitm 10/22, DNS 5/12, HDMI 6/9, remote-control 12/16, **undecryptable reported, narrow probe 1, wide probe 3** (see §6b) |
 | Q13 | ''crawlConfig'' fields stated | 6 papers with a ''crawlConfig'' | ''interactionDepth'' 5, ''consentAction'' 0, ''statefulness'' 0, ''browsers'' 0 | | Q13 | ''crawlConfig'' fields stated | 6 papers with a ''crawlConfig'' | ''interactionDepth'' 5, ''consentAction'' 0, ''statefulness'' 0, ''browsers'' 0 |
 | Q14 | ''ethics.reviewOutcome'' stated | 34 with an ''ethics'' object | 14 (41.2%) vs corpus-empirical 1,728 of 4,472 (38.6%) | | Q14 | ''ethics.reviewOutcome'' stated | 34 with an ''ethics'' object | 14 (41.2%) vs corpus-empirical 1,728 of 4,472 (38.6%) |
 | Q15 | ''artifacts.availability'' stated | 34 with an ''artifacts'' object | 27 (79.4%) vs 2,890 of 4,854 (59.5%) | | Q15 | ''artifacts.availability'' stated | 34 with an ''artifacts'' object | 27 (79.4%) vs 2,890 of 4,854 (59.5%) |
-| Q16 | ''temporal.spanStart'' stated | 33 empirical | 27 (79.4%) vs 2,882 of 5,118 (56.3%) |+| Q16 | ''temporal.spanStart'' stated | 34 empirical | 27 (79.4%) vs 2,882 of 5,118 (56.3%) |
 | Q17 | ''detection[].prevalence'' coverage | 70 Tier A tuples | 68 carry a prevalence (97.1%); corpus-wide 26,316 of 27,241 (96.6%) | | Q17 | ''detection[].prevalence'' coverage | 70 Tier A tuples | 68 carry a prevalence (97.1%); corpus-wide 26,316 of 27,241 (96.6%) |
 | Q18 | ''population[].listVersion'' stated | 105 population tuples in the 35 | 42 | | Q18 | ''population[].listVersion'' stated | 105 population tuples in the 35 | 42 |
 | Q19 | Vantage location stated | 34 with a ''vantage'' tuple | 18 (52.9%) | | Q19 | Vantage location stated | 34 with a ''vantage'' tuple | 18 (52.9%) |
  
-**Denominators that are easy to get wrong here, spelled out.** ''ethics'' and ''artifacts'' are nullable in the schema — one of the 35 papers has neither object — so Q14–Q16 divide by the papers that carry the object, never by 35 and never by the corpus. ''crawlConfig'' is null for 29 of the 35, so Q13 divides by 6, and its zeros are read on the page rather than reported bare. Nothing on either page divides by 5,859.+**Denominators that are easy to get wrong here, spelled out.** ''ethics'' and ''artifacts'' are nullable in the schema — one of the 35 papers has neither object — so Q14–Q16 divide by the papers that carry the object, never by 35 and never by the corpus. ''crawlConfig'' is null for 29 of the 35, so Q13 divides by 6, and its zeros are read on the page rather than reported bare. No **TV** figure on either page divides by 5,859. The one place that denominator appears is the corpus-share column of the platform table on the content page, which exists precisely to say what share of the whole corpus each platform value has — that column divides by 5,859 by design, and is labelled as doing so. An earlier version of this sentence said "nothing on either page divides by 5,859", which was wrong.
  
 ===== 4. The candidate pool, and why it has two gates ===== ===== 4. The candidate pool, and why it has two gates =====
Line 85: Line 85:
 The 39 papers dropped between the gates all have a single-brand, low-count mention — a ''Tizen'' in a list of embedded platforms, one ''Apple TV'' in an enumeration of Apple hardware. That is a **judgement, not a measurement**: it was not hand-audited, and if a television study exists that names exactly one TV-class device three times or fewer, this page does not contain it. A wider audit would be the cheapest improvement to make here. The 39 papers dropped between the gates all have a single-brand, low-count mention — a ''Tizen'' in a list of embedded platforms, one ''Apple TV'' in an enumeration of Apple hardware. That is a **judgement, not a measurement**: it was not hand-audited, and if a television study exists that names exactly one TV-class device three times or fewer, this page does not contain it. A wider audit would be the cheapest improvement to make here.
  
-**Homonyms found, and what they cost.** ''ACR'' is the American College of Radiology, an //authentication context reference//, and an arbitrary abbreviation in a privacy-policy paper; ''IPTV'' appears in leaked-credential corpora and in X spam campaigns; ''Tizen'' is a smartwatch platform and an open-source project under fuzz testing; ''WebOS'' matches both the LG TV OS and unrelated prose. **52 of 103 audit-set papers are OUT**, and the biggest single class is the smart-home survey, where "smart TV" is an answer option. The precision of the audit set is **34.0%** — for comparison, the ad-archives row on [[roadmap]] recorded 14.5% and the authentication row 24.5%.+**Homonyms found, and what they cost.** ''ACR'' is the American College of Radiology, an //authentication context reference//, and an arbitrary abbreviation in a privacy-policy paper; ''IPTV'' appears in leaked-credential corpora and in X spam campaigns; ''Tizen'' is a smartwatch platform and an open-source project under fuzz testing; ''WebOS'' matches both the LG TV OS and unrelated prose. **52 of 103 audit-set papers are OUT**, and the biggest single class is the smart-home survey, where "smart TV" is an answer option. The precision of the audit set is **34.0%** — for comparison, the ad-archives row on [[:roadmap]] recorded 14.5% and the authentication row 24.5%.
  
 ===== 5. Verdict map — the 68 papers NOT in the population ===== ===== 5. Verdict map — the 68 papers NOT in the population =====
Line 213: Line 213:
 ============================================================================== ==============================================================================
 </code> </code>
 +
 +==== 5b. The guard on this map, mutation-tested ====
 +
 +A review pass on 2026-09-12 mutation-tested the map rather than reading it, and found the guard was weaker than it looked.
 +
 +  * **Deleting an entry** — the script throws: ''audit set has 1 slug(s) with no verdict in ctv_fold.mjs''. Working as documented.
 +  * **Flipping a tier letter** on a paper that stays in the candidate set — ''B'' to ''OUT'' on //Tracking You from a Thousand Miles Away// — **the script exited 0**, silently recomputed the population as 34 instead of 35 and ''OUT'' as 53 instead of 52, and every percentage on the content page would have moved with it. No assertion fired, because the only check was a slug-set difference.
 +
 +**Fixed the same day**, by pinning the split to what [[design:connected_tv]] publishes:
 +
 +<code>
 +const PUBLISHED_SPLIT = { A: 13, B: 22, ADJ: 16, OUT: 52 };
 +</code>
 +
 +**And that fix was itself insufficient — found by the next review pass, on 2026-09-13.** A count is not a membership. Mutating two entries at once, **swapping** a genuine Tier B paper out and a genuine ''OUT'' paper in, leaves all four counts identical and exits 0, while the population silently acquires a paper that is not about television at all. The reviewer demonstrated it with //BLERP: BLE Re-Pairing Attacks and Defenses// (B to OUT) against a bilingual privacy-policy paper whose only TV content is an ''ACR'' homonym (OUT to B): platform ''web'' went from 1 to 2, PETS 6 to 7, NDSS 6 to 5, and the ''iot'' share from 74.3% to 71.4% — every one of them a published figure, none of them guarded.
 +
 +So membership itself is now pinned, per tier, as a digest of the sorted slug list — and the ''topic'' tag, which had no guard at all and drives the ''iot-device-set'' list on the content page, is pinned the same way:
 +
 +<code>
 +const PUBLISHED_MEMBERS = {
 +  A: 'b7410e5f7a33a91e', B: '4a71c82990115cdf', ADJ: '1eb63ba64295cda8', OUT: '22530ed51f0ceb35',
 +};
 +const PUBLISHED_TOPICS = 'fdb92e2a4c3ab263';
 +</code>
 +
 +Re-run on 2026-09-13, all four mutations now fail and the unmutated script exits 0:
 +
 +^ Mutation ^ Before 2026-09-13 ^ Now ^
 +| Delete a map entry | throws | throws (''audit set has 1 slug(s) with no verdict'') |
 +| Flip one tier letter | throws (since 2026-09-12) | throws (''verdict split moved'') |
 +| **Swap two papers between tiers** | **exit 0, population silently wrong** | throws (''tier B membership changed'') |
 +| **Change a topic tag only** | **exit 0, the iot-device-set list silently wrong** | throws (''topic assignments … changed'') |
 +
 +The lesson worth carrying: the round-1 fix was written by reading the failure the reviewer demonstrated, and it closed exactly that failure and nothing adjacent to it. Only a second mutation test, by a second reviewer with the same brief, found the hole next to it.
  
 ===== 6. Folding, and the residue in full ===== ===== 6. Folding, and the residue in full =====
Line 218: Line 252:
 Two folds are used, and only one aggregates anything. Two folds are used, and only one aggregates anything.
  
-**Tool-name alias fold.** ''report_connected_tv.mjs'' maps a lower-cased alphanumeric skeleton of each ''tools[].name'' onto a canonical display name, for 25 skeletons: ''mitmproxy / mitmdump / mitmweb'' to //mitmproxy//, ''wireshark / tshark'' to //Wireshark//, ''adb / androiddebugbridge'' to //adb//, ''charles / charlesproxy'' to //Charles Proxy//, plus one-to-one entries for tcpdump, Frida, Pi-hole, VirusTotal, apktool, jadx, FlowDroid, LibScout, EasyList, Scapy, Selenium, OpenWPM, Mercury, PingPong, Appium, Raspberry Pi, Monkey and UIAutomator. Only ''usedOrMentioned == "used"'' tuples are counted, and the unit is the paper.+**Tool-name alias fold.** ''report_connected_tv.mjs'' maps a lower-cased alphanumeric skeleton of each ''tools[].name'' onto a canonical display name, for **27 skeletons mapping onto 22 canonical names**: ''mitmproxy / mitmdump / mitmweb'' to //mitmproxy//, ''wireshark / tshark'' to //Wireshark//, ''adb / androiddebugbridge'' to //adb//, ''charles / charlesproxy'' to //Charles Proxy//, plus one-to-one entries for tcpdump, Frida, Pi-hole, VirusTotal, apktool, jadx, FlowDroid, LibScout, EasyList, Scapy, Selenium, OpenWPM, Mercury, PingPong, Appium, Raspberry Pi, Monkey and UIAutomator. Only ''usedOrMentioned == "used"'' tuples are counted, and the unit is the paper.
  
 **The unmapped residue is 191 distinct raw tool names** across the 35 papers. Printed in full, because a residue that lives only in a local file is a residue nobody reads — and because in this case reading it is how the broadcast-side instruments were found: **The unmapped residue is 191 distinct raw tool names** across the 35 papers. Printed in full, because a residue that lives only in a local file is a residue nobody reads — and because in this case reading it is how the broadcast-side instruments were found:
Line 263: Line 297:
 </code> </code>
  
-Nothing in the residue was silently merged and nothing was dropped: the page's instrument table is exactly the 25-alias slice, and the residue is everything else. **The residue is the interesting half here.** ''Avalpa OpenCaster'', ''TSDuck'', ''DekTec DTU-215'', ''HiDes UT-100c'', ''Afatech AF9015'' and ''RedOrbit HbbTV Emulator'' are DVB modulation and stream-authoring tools with no counterpart anywhere else on this wiki; ''IRDB'', ''irgen'', ''IrScrutinizer'', ''MakeHex'' and ''VS1838B'' are infrared remote tooling; ''HDMI Video Capture Device'', ''Roku External Control Protocol'', ''tvbus.exe'' and ''NoxPlayer'' are TV-specific automation. A fold that had merged these into "other" would have hidden the page's most useful finding.+Nothing in the residue was silently merged and nothing was dropped: the page's instrument table is exactly the 27-alias slice, and the residue is everything else. **The residue is the interesting half here.** ''Avalpa OpenCaster'', ''TSDuck'', ''DekTec DTU-215'', ''HiDes UT-100c'', ''Afatech AF9015'' and ''RedOrbit HbbTV Emulator'' are DVB modulation and stream-authoring tools with no counterpart anywhere else on this wiki; ''IRDB'', ''irgen'', ''IrScrutinizer'', ''MakeHex'' and ''VS1838B'' are infrared remote tooling; ''HDMI Video Capture Device'', ''Roku External Control Protocol'', ''tvbus.exe'' and ''NoxPlayer'' are TV-specific automation. A fold that had merged these into "other" would have hidden the page's most useful finding.
  
 **No fold is applied to ''vantage.locations'' or ''population.sourceList''**, and both are published unfolded on the content page as **rankings only**, never as percentages. This is deliberate: at //n//=35 the folding error that [[literature:corpus]] measures on the vantage field (280 versus 498 for the United States, corpus-wide) is not worth introducing, and the raw strings — "Apartment 1", "lab space", "241 countries and territories", "e-bike route" — are themselves informative about what a TV vantage point is. **No fold is applied to ''vantage.locations'' or ''population.sourceList''**, and both are published unfolded on the content page as **rankings only**, never as percentages. This is deliberate: at //n//=35 the folding error that [[literature:corpus]] measures on the vantage field (280 versus 498 for the United States, corpus-wide) is not worth introducing, and the raw strings — "Apartment 1", "lab space", "241 countries and territories", "e-bike route" — are themselves informative about what a TV vantage point is.
Line 271: Line 305:
 ''scripts/ctv_quotecheck.py'' matches every phrase either page quotes, or leans on for a figure, against **both** ''paper.cols.txt'' and the PDF text layer via pypdf. Both are needed, and this run proves why: ''scripts/ctv_quotecheck.py'' matches every phrase either page quotes, or leans on for a figure, against **both** ''paper.cols.txt'' and the PDF text layer via pypdf. Both are needed, and this run proves why:
  
-  * **28 of 33** located in both renderings.+  * **36 of 41** located in both renderings. (It was 28 of 33 until 2026-09-13; round 2 added eight needles, all of which land in both renderings — see below.)
   * **2 in ''.cols'' only** — the FingerprinTV DBF sentence and the Roku ECP URL, which the PDF text layer scrambles.   * **2 in ''.cols'' only** — the FingerprinTV DBF sentence and the Roku ECP URL, which the PDF text layer scrambles.
   * **3 in the PDF only** — de-columning splices. The clearest is {[kumar2019_things]}: the sentence "the most popular vendor, Roku, only accounts for 17.4% of media devices" is spliced in ''.cols'' into "nd the most poputions of IoT device types, except when a device type accounts lar vendor, Roku, only accounts for 17.4% of media devices for fewer than 1% of devices". A ''.cols''-only check would have reported a correct quote as NOTFOUND.   * **3 in the PDF only** — de-columning splices. The clearest is {[kumar2019_things]}: the sentence "the most popular vendor, Roku, only accounts for 17.4% of media devices" is spliced in ''.cols'' into "nd the most poputions of IoT device types, except when a device type accounts lar vendor, Roku, only accounts for 17.4% of media devices for fewer than 1% of devices". A ''.cols''-only check would have reported a correct quote as NOTFOUND.
   * **0 in neither.**   * **0 in neither.**
 +
 +**Eight needles were added on 2026-09-13**, for the claims the round-2 review changed. They are worth listing because each one existed //on the page// before it existed in this checker — which is the drift this file is supposed to prevent:
 +
 +^ Needle ^ Why it was added ^
 +| ''to bypass certificate pinning'' ({[moghaddam2019_watching]}) | the widened TLS-decryption probe; the narrow probe missed this sentence while the page quoted it |
 +| ''we cannot install our own self-signed certificates on the Roku'' ({[varmarken2020_smart]}) | same |
 +| ''there is no way to install custom certificates on Android TV'' ({[tileria2022_watch]}) | same |
 +| ''We perform a factory reset of the TV for each channel analysis'' ({[tagliaro2023_still]}) | refutes the page's old "no paper states whether the device was factory-reset". Note the needle stops where it does: the full sentence is **spliced in ''.cols''** by the de-columner, which interleaves it with "and the UT-100c HiDes modulator" |
 +| ''download the last version of each app (as of August 2020) from AndroZoo'' ({[tileria2022_watch]}) | refutes "every paper built its own set" |
 +| ''we randomly selected 1.5K unique package names from Androzoo'' ({[girish2023_room]}) | same |
 +| ''published a candidate standard for hybrid TV in America'' ({[oren2014_aether]}) | the single real ATSC mention in all 5,859 papers |
 +| ''this time enabling the "Limit Ad Tracking" … "Disable Interest-based Ads" … settings'' ({[moghaddam2019_watching]}) | refutes "exactly one paper measures both sides of the opt-out" |
  
 **One needle was genuinely wrong, and the check caught it.** The first draft asserted "decryption fails for 1 out of 5 (or fewer) TLS connections for 80% of all apps" against {[varmarken2020_smart]}. The paper says //"decryption fails for 1 out of 10 (or fewer) TLS connections for 55% of all apps; 1 out of 5 (or fewer) TLS connections for 80% of all apps"// — two clauses, and the draft had glued the opening of the first to the end of the second, producing a sentence the paper does not contain. The needle was narrowed to the clause that is actually there. This is the reason bare-number needles are avoided in that script. **One needle was genuinely wrong, and the check caught it.** The first draft asserted "decryption fails for 1 out of 5 (or fewer) TLS connections for 80% of all apps" against {[varmarken2020_smart]}. The paper says //"decryption fails for 1 out of 10 (or fewer) TLS connections for 55% of all apps; 1 out of 5 (or fewer) TLS connections for 80% of all apps"// — two clauses, and the draft had glued the opening of the first to the end of the second, producing a sentence the paper does not contain. The needle was narrowed to the clause that is actually there. This is the reason bare-number needles are avoided in that script.
Line 314: Line 360:
 cols+pdf  IMC 2011 understanding-couch-potatoes-measurement-and "The average number of set-top boxes provisioned was approximately " cols+pdf  IMC 2011 understanding-couch-potatoes-measurement-and "The average number of set-top boxes provisioned was approximately "
 cols+pdf  USENIX 2019 all-things-considered-an-analysis-of-iot-dev "are the most common type of device in seven of the eleven regions" cols+pdf  USENIX 2019 all-things-considered-an-analysis-of-iot-dev "are the most common type of device in seven of the eleven regions"
 +cols+pdf  CCS 2019 watching-you-watch-the-tracking-ecosystem-of "to bypass certificate pinning"
 +cols+pdf  PETS 2020 the-tv-is-smart-and-full-of-trackers-measuri "we cannot install our own self-signed certificates on the Roku"
 +cols+pdf  PETS 2022 watch-over-your-tv-a-security-and-privacy-an "there is no way to install custom certificates on Android TV"
 +cols+pdf  NDSS 2023 i-still-know-what-you-watched-last-sunday-pr "We perform a factory reset of the TV for each channel analysis"
 +cols+pdf  PETS 2022 watch-over-your-tv-a-security-and-privacy-an "download the last version of each app (as of August 2020) from And"
 +cols+pdf  IMC 2023 in-the-room-where-it-happens-characterizing- "we randomly selected 1.5K unique package names from Androzoo"
 +cols+pdf  USENIX 2014 from-the-aether-to-the-ethernet-attacking-th "published a candidate standard for hybrid TV in America"
 +cols+pdf  CCS 2019 watching-you-watch-the-tracking-ecosystem-of "this time enabling the "Limit Ad Tracking" (Roku) and the "Disable"
  
-33 quotes: 28 in both renderings, 2 in .cols only, 3 in the PDF only, 0 in neither.+41 quotes: 36 in both renderings, 2 in .cols only, 3 in the PDF only, 0 in neither.
 </code> </code>
  
Line 325: Line 379:
 | HbbTV 2.0.5, published 2026-02-25, incremental over 2.0.4 (March 2023) | HbbTV Association specifications page | fetched; the version table lists 1.0 (2010) through 2.0.5 (2026-02-25) | | HbbTV 2.0.5, published 2026-02-25, incremental over 2.0.4 (March 2023) | HbbTV Association specifications page | fetched; the version table lists 1.0 (2010) through 2.0.5 (2026-02-25) |
 | Roku ECP is "a simple RESTful API accessed using HTTP on port 8060", no authentication documented | Roku developer docs, External Control API | fetched; the port and the ''query/device-info'' endpoint quoted verbatim. Cross-checked against {[moghaddam2019_watching]}, which uses the same URL form | | Roku ECP is "a simple RESTful API accessed using HTTP on port 8060", no authentication documented | Roku developer docs, External Control API | fetched; the port and the ''query/device-info'' endpoint quoted verbatim. Cross-checked against {[moghaddam2019_watching]}, which uses the same URL form |
-| RIDA, ''GetRida()'' / ''IsRidaDisabled()'', 30-day temporary ID under limit-ad-tracking | Roku developer docs, Roku Advertising Framework | fetched |+| RIDA, ''GetRIDA()'' / ''IsRIDADisabled()'', 30-day temporary ID under limit-ad-tracking | Roku developer docs: ''integrating-roku-advertising-framework'' for ''GetRIDA()'' and the 30-day ID''ifDeviceInfo'' for ''IsRIDADisabled()'' (which is //not// on the RAF page) | fetched; re-verified 2026-09-13 |
 | TIFA, ''getTIFA()'' / ''isLATEnabled()'', resettable, "no connection to any PII … or DUID" | Samsung Smart TV developer docs | fetched from the ''unique-identifiers-for-smarttv'' guide | | TIFA, ''getTIFA()'' / ''isLATEnabled()'', resettable, "no connection to any PII … or DUID" | Samsung Smart TV developer docs | fetched from the ''unique-identifiers-for-smarttv'' guide |
 | Fire TV Advertising ID, ''advertising_id'' / ''limit_ad_tracking'', Fire OS 5.2.1.1+ on TV | Amazon Developer Policy Center, Advertising ID Policy | fetched | | Fire TV Advertising ID, ''advertising_id'' / ''limit_ad_tracking'', Fire OS 5.2.1.1+ on TV | Amazon Developer Policy Center, Advertising ID Policy | fetched |
Line 338: Line 392:
  
 **Rejected, and why.** A search for recent ACR measurement returned several consumer-facing articles (a "how to disable ACR in 2026" listicle, a cybersecurity blog summarising the IMC paper, a compliance vendor's education page) which between them asserted the LG-15-seconds and Samsung-per-minute cadences, the Texas lawsuit and the Samsung settlement. **None was used.** The cadences were taken from {[anselmi2024_watching]}'s own text, and the enforcement dates from the Attorney General's releases. One of those articles also attributed the "every 500 milliseconds" figure to the research paper; it is the regulator's pleading, and the paper's own 500 ms figure is an estimate of Samsung's //capture// rate. The content page keeps those two apart deliberately. **Rejected, and why.** A search for recent ACR measurement returned several consumer-facing articles (a "how to disable ACR in 2026" listicle, a cybersecurity blog summarising the IMC paper, a compliance vendor's education page) which between them asserted the LG-15-seconds and Samsung-per-minute cadences, the Texas lawsuit and the Samsung settlement. **None was used.** The cadences were taken from {[anselmi2024_watching]}'s own text, and the enforcement dates from the Attorney General's releases. One of those articles also attributed the "every 500 milliseconds" figure to the research paper; it is the regulator's pleading, and the paper's own 500 ms figure is an estimate of Samsung's //capture// rate. The content page keeps those two apart deliberately.
 +
 +**One dead link, and it is in the corpus's own data.** The artifact URL the extraction recovered for {[gopalakrishnan2011_couch]} — ''www.research.att.com/~kkrama/papers/streamcontrol.pdf'' — returns **HTTP 403** over both http and https and with the tilde encoded. It appears in this page's artifact listing because it is what the paper stated, not because anything on either page rests on it; it is left in place as a record of the paper's own claim. Every URL actually cited as evidence on [[design:connected_tv]] returns 200.
  
 Two further checks worth recording. The Mon(IoT)r testbed software is live at ''github.com/djdubois/moniotr-core'' (last pushed 2024-08-09) but the lab's tools page does not publish a smart-TV dataset for download, so the page describes testbed captures as a route without promising a TV dataset exists to fetch. And the PETS landing pages were used to recover author lists for five entries the corpus index lacks; {[ahmed2022_analyzing]}'s authors were additionally cross-checked against Crossref because its stored PDF has no usable text layer on the title page. Two further checks worth recording. The Mon(IoT)r testbed software is live at ''github.com/djdubois/moniotr-core'' (last pushed 2024-08-09) but the lab's tools page does not publish a smart-TV dataset for download, so the page describes testbed captures as a route without promising a TV dataset exists to fetch. And the PETS landing pages were used to recover author lists for five entries the corpus index lacks; {[ahmed2022_analyzing]}'s authors were additionally cross-checked against Crossref because its stored PDF has no usable text layer on the title page.
 +
 +==== 8b. Sources added or corrected in round 2 (2026-09-13) ====
 +
 +^ Claim ^ Primary source, and how it was checked ^ Result ^
 +| ATSC 3.0 broadcaster applications: ''advertisingId'', ''filterCode'', receiver cookies | ATSC **A/344:2026-04**, //ATSC 3.0 Interactive Content//, 14 April 2026. PDF downloaded (HTTP 200, 2,363,014 bytes, 202 pages), text extracted with ''pypdf'', each needle matched in whitespace-collapsed text | All five quotes FOUND verbatim. ''data collection'' returns **0 hits** in the whole standard — the phrase the withdrawn 2016 quote used |
 +| A/344 current revision | [[https://www.atsc.org/atsc-documents/3442017-atsc-3-0-interactive-content/|the A/344 document page]] lists 2026-04 (14 April 2026) above 2026-02; the 2026-04 PDF's own title block reads ''A/344:2026-04'' | **2026-04**, not the 2026-02 the author first downloaded. One round-2 reviewer read the standards listing as showing 2025-07 as the latest approved; the PDF's own designation settles it |
 +| EU: joint Article 62 GDPR operation on smart TVs | [[https://www.autoriteitpersoonsgegevens.nl/documenten/rapport-verkennend-onderzoek-smart-tvs|Autoriteit Persoonsgegevens]] landing page (HTTP 200) and the report PDF (HTTP 200, 1,005,269 bytes, 14 pages), both needing a browser User-Agent and a Referer header | Real. NL/HU/IT/LI, published 23 September 2025. The off-state percentages (97.52 / 98.84 / 91.10) read out of the PDF's own table |
 +| UK: ICO connected-TV programme | [[https://ico.org.uk/about-the-ico/media-centre/news-and-blogs/2026/06/setting-out-our-expectations-for-the-smart-device-industry/|ICO news release]], 11 June 2026 (HTTP 403 to a bare fetcher, HTTP 200 with a browser User-Agent) | Real. Quote and attribution to William Malcolm verified in the fetched HTML |
 +| Walmart press release names ''Platform+'' | [[https://corporate.walmart.com/news/2024/12/03/walmart-completes-acquisition-of-vizio|the release]] (HTTP 200, 180,202 bytes), searched after **double** HTML-entity decoding | **It does.** The round-1 footnote said it did not. The plus sign is entity-encoded, so a tag-strip-only search misses it — this is why the check has to decode entities, not just strip tags. ''Inscape'' is genuinely absent |
 +| ''ahn2025_watch'' Zenodo access | Zenodo REST API, ''records/15646588'' (HTTP 200): ''access_right: open'', CC-BY-4.0, title ends ''[Public Artifact]'' | The paper has **two** records; the extraction's ''restricted'' is true of ''zenodo.15602938'' only. Round 1 attached the label to the open DOI |
 +| FingerprinTV code release | [[https://github.com/UCI-Networking-Group/fingerprintv|README]] fetched raw (HTTP 200) | "The FingerprinTV dataset has already been released." / "Once it is ready for release to the public, the code will be added to this repository. Please stay tuned." Four years on |
 +| FCC Fifth FNPRM is still pending | Checked for a Report and Order; none found as of 2026-09-13. The adopted item is **FCC 25-72**, adopted 2025-10-28, released 2025-10-29 | The page's fact-sheet citation stands. One reviewer surfaced a trade-press claim of a May 2026 FCC vote mandating ATSC 3.0 tuners; it appears nowhere on fcc.gov and is **rejected** |
 +
 +**Rejected in round 2.** A blog URL for "ADB Wi-Fi 2.0" offered in round 1 returns 404 and stays rejected; the claim rests on ''developer.android.com/tools/adb'' instead. The trade-press "FCC voted 3–2 in May 2026" story is rejected as above. Samsung's briefly-vacated TRO is still judged a procedural detail and stays off the content page.
  
 ===== 9. Bibliography ===== ===== 9. Bibliography =====
  
-**31 entries were added** to [[literature:bibliography]] in this sittinggenerated by ''scripts/bibgen.mjs'' from ''data/corpus2/.meta'' so authors, titles and DOIs are publisher metadata rather than recall. Checks run before appending:+**32 entries were added** to [[literature:bibliography]] in this sitting — 31 in the first pass and {[zhu2020_alexa]} added after review (see §15) — generated by ''scripts/bibgen.mjs'' from ''data/corpus2/.meta'' so authors, titles and DOIs are publisher metadata rather than recall. Checks run before appending:
  
   * **Citekey collisions**: none of the 31 keys exists in the live bibliography.   * **Citekey collisions**: none of the 31 keys exists in the live bibliography.
Line 606: Line 676:
 import fs from 'node:fs'; import fs from 'node:fs';
 import path from 'node:path'; import path from 'node:path';
 +import { createHash } from 'node:crypto';
 import { loadExtractions, dataRoot, isSentinel, pct, table, wikiTable } from './lib.mjs'; import { loadExtractions, dataRoot, isSentinel, pct, table, wikiTable } from './lib.mjs';
 import { MAP } from './ctv_fold.mjs'; import { MAP } from './ctv_fold.mjs';
Line 678: Line 749:
 const POP = [...A, ...B];                       // the page's population const POP = [...A, ...B];                       // the page's population
 const nA = A.length, nB = B.length, nPOP = POP.length; const nA = A.length, nB = B.length, nPOP = POP.length;
 +
 +// The slug-set check above only catches a slug appearing or disappearing. A
 +// mutation test on 2026-09-12 showed that FLIPPING a tier letter — 'B' to 'OUT'
 +// on a paper that stays in the candidate set — passed every assertion and
 +// silently moved the population from 35 to 34, changing every percentage on the
 +// page. So the split itself is pinned to what design:connected_tv publishes.
 +// Changing the map deliberately means changing these four numbers too.
 +const PUBLISHED_SPLIT = { A: 13, B: 22, ADJ: 16, OUT: 52 };
 +const actualSplit = { A: nA, B: nB, ADJ: ADJ.length, OUT: OUT.length };
 +for (const k of Object.keys(PUBLISHED_SPLIT)) {
 +  if (actualSplit[k] !== PUBLISHED_SPLIT[k])
 +    throw new Error(
 +      `verdict split moved: ${k} is ${actualSplit[k]}, design:connected_tv publishes ${PUBLISHED_SPLIT[k]}. ` +
 +      `Full split now ${JSON.stringify(actualSplit)} against published ${JSON.stringify(PUBLISHED_SPLIT)}. ` +
 +      `If the map change is intended, update PUBLISHED_SPLIT and every figure on the page.`
 +    );
 +}
 +const splitTotal = nA + nB + ADJ.length + OUT.length;
 +if (splitTotal !== AUDIT.length)
 +  throw new Error(`verdicts sum to ${splitTotal} but the audit set is ${AUDIT.length}`);
 +
 +// A second mutation test, on 2026-09-13, broke the four counts above: SWAPPING
 +// two papers between tiers — one genuine Tier B out, one genuine OUT in —
 +// leaves A/B/ADJ/OUT unchanged and exits 0, while the population silently gains
 +// a paper that is not about television (platform 'web' went 1 -> 2, the venue
 +// and year tables both moved). Counts are not membership. So the membership
 +// itself is pinned, per tier, as a digest of the sorted slug list.
 +const digest = (rows) => createHash('sha256')
 +  .update(rows.map((x) => x.p.slug).sort().join('\n')).digest('hex').slice(0, 16);
 +const PUBLISHED_MEMBERS = {
 +  A: 'b7410e5f7a33a91e', B: '4a71c82990115cdf', ADJ: '1eb63ba64295cda8', OUT: '22530ed51f0ceb35',
 +};
 +const actualMembers = { A: digest(A), B: digest(B), ADJ: digest(ADJ), OUT: digest(OUT) };
 +for (const k of Object.keys(PUBLISHED_MEMBERS)) {
 +  if (actualMembers[k] !== PUBLISHED_MEMBERS[k])
 +    throw new Error(
 +      `tier ${k} membership changed (count is still ${actualSplit[k]}, so the count check above could not see it). ` +
 +      `digest is ${actualMembers[k]}, design:connected_tv was published against ${PUBLISHED_MEMBERS[k]}. ` +
 +      `Full digests now ${JSON.stringify(actualMembers)}. If the map change is intended, update ` +
 +      `PUBLISHED_MEMBERS and re-check every per-venue, per-year, per-platform and per-topic figure on the page.`
 +    );
 +}
 +
 +// The topic tag has no count to pin — it is hand-assigned and published as a
 +// ranking. It still drives the "Fifteen of the 35 papers are IoT studies" list,
 +// so its membership is pinned the same way.
 +const topicDigest = createHash('sha256').update(
 +  Object.entries(MAP).filter(([, v]) => v[0] === 'A' || v[0] === 'B')
 +    .map(([s, v]) => `${s}\t${v[1]}`).sort().join('\n')).digest('hex').slice(0, 16);
 +const PUBLISHED_TOPICS = 'fdb92e2a4c3ab263';
 +if (topicDigest !== PUBLISHED_TOPICS)
 +  throw new Error(
 +    `topic assignments for the 35-paper population changed: digest ${topicDigest}, published against ${PUBLISHED_TOPICS}. ` +
 +    `Update PUBLISHED_TOPICS and re-check the "What this literature measures" table and the iot-device-set list on the page.`
 +  );
  
 H('0. CANDIDATE POOL AND AUDIT'); H('0. CANDIDATE POOL AND AUDIT');
Line 819: Line 945:
 T(['population.samplingMethod', 'papers'], [...new Set(POP.flatMap((x) => x.p.population.map((q) => q.samplingMethod)))] T(['population.samplingMethod', 'papers'], [...new Set(POP.flatMap((x) => x.p.population.map((q) => q.samplingMethod)))]
   .map((m) => [m, POP.filter((x) => x.p.population.some((q) => q.samplingMethod === m)).length]).sort((a, b) => b[1] - a[1]));   .map((m) => [m, POP.filter((x) => x.p.population.some((q) => q.samplingMethod === m)).length]).sort((a, b) => b[1] - a[1]));
-const devSets = POP.map((x) => ({ k: `${x.p.venue} ${x.p.year}`, ns: x.p.population.filter((q) => q.unit === 'iot-devices' && q.n !== null).map((q) => q.n) })) +// Labelled by slug, not `venue year`: there are two IMC 2011 papers in this 
-  .filter((r) => r.ns.length);+// population and only one of them has iot-devices tuples, so a venue+year label 
 +// is ambiguous exactly where a reader would want to check it. 
 +const devSets = POP.map((x) => ({ 
 +  k: `${x.p.venue} ${x.p.year} ${x.p.slug.slice(0, 38)}`, 
 +  ns: x.p.population.filter((q) => q.unit === 'iot-devices' && q.n !== null).map((q) => q.n)
 +})).filter((r) => r.ns.length);
 T(['paper', 'iot-devices n values stated'], devSets.map((r) => [r.k, r.ns.join(', ')])); T(['paper', 'iot-devices n values stated'], devSets.map((r) => [r.k, r.ns.join(', ')]));
 +
 +// The page states this distribution in prose, so it is derived here rather than
 +// eyeballed off the table above. A hand-typed version of this list shipped in
 +// the first draft and omitted 57 — the PETS 2020 testbed, the population's own
 +// flagship paper.
 +const allNs = devSets.flatMap((r) => r.ns).sort((a, b) => a - b);
 +const largestPer = devSets.map((r) => Math.max(...r.ns)).sort((a, b) => a - b);
 +const median = (arr) => (arr.length % 2
 +  ? arr[(arr.length - 1) / 2]
 +  : (arr[arr.length / 2 - 1] + arr[arr.length / 2]) / 2);
 +console.log(`\npapers stating an iot-devices size : ${devSets.length} of ${nPOP}`);
 +console.log(`stated size values                : ${allNs.length}`);
 +console.log(`all values, sorted                : ${allNs.join(', ')}`);
 +console.log(`median of all stated values       : ${median(allNs)}`);
 +console.log(`largest set per paper, sorted     : ${largestPer.join(', ')}`);
 +console.log(`median of largest-per-paper       : ${median(largestPer)}`);
 +for (const cut of [100, 200, 1000]) {
 +  console.log(`papers whose LARGEST set <= ${String(cut).padStart(4)}   : ${largestPer.filter((v) => v <= cut).length} of ${devSets.length}`);
 +}
 +console.log('papers whose largest set is over 200, i.e. not a lab bench:');
 +for (const r of devSets.filter((r) => Math.max(...r.ns) > 200)) console.log(`  ${r.k}  -> ${r.ns.join(', ')}`);
 const listv = POP.flatMap((x) => x.p.population).filter((q) => q.listVersion !== null).length; const listv = POP.flatMap((x) => x.p.population).filter((q) => q.listVersion !== null).length;
 console.log(`\npopulation tuples in A+B stating a listVersion: ${listv} of ${POP.flatMap((x) => x.p.population).length}`); console.log(`\npopulation tuples in A+B stating a listVersion: ${listv} of ${POP.flatMap((x) => x.p.population).length}`);
Line 878: Line 1030:
     `${EMP_CORPUS.filter((p) => p.temporal.some((t) => t.spanStart !== null)).length} of ${EMP_CORPUS.length} (${pct(EMP_CORPUS.filter((p) => p.temporal.some((t) => t.spanStart !== null)).length, EMP_CORPUS.length)})`],     `${EMP_CORPUS.filter((p) => p.temporal.some((t) => t.spanStart !== null)).length} of ${EMP_CORPUS.length} (${pct(EMP_CORPUS.filter((p) => p.temporal.some((t) => t.spanStart !== null)).length, EMP_CORPUS.length)})`],
 ]); ]);
 +function linkOf(a) {
 +  if (a.codeUrl) return a.codeUrl;
 +  if (a.dataUrl) return a.dataUrl;
 +  if (!a.links || a.links.length === 0) return '—';
 +  const l = a.links[0];
 +  if (typeof l === 'string') throw new Error(`artifacts.links[0] is a string, expected an object: ${l}`);
 +  return `${l.url}  (${l.kind}; ${l.what}; authors=${l.belongsToAuthors})`;
 +}
 +
 console.log('\nArtifact links released, Tier A:'); console.log('\nArtifact links released, Tier A:');
 for (const x of A) console.log(x.p.artifacts === null for (const x of A) console.log(x.p.artifacts === null
   ? `  ${x.p.venue} ${x.p.year}  (no artifacts object extracted)`   ? `  ${x.p.venue} ${x.p.year}  (no artifacts object extracted)`
-  : `  ${x.p.venue} ${x.p.year}  ${x.p.artifacts.availability.padEnd(22)} ${(x.p.artifacts.codeUrl || x.p.artifacts.dataUrl || x.p.artifacts.links[0] || '\u2014')}`);+  // artifacts.links[] entries are OBJECTS ({url, kind, what, belongsToAuthors}). 
 +  // Falling back to links[0] itself string-coerced to "[object Object]" and that 
 +  // literal was published three times on the provenance page \u2014 found by a review 
 +  // pass on 2026-09-13. Take .url, and print what the link is for. 
 +  : `  ${x.p.venue} ${x.p.year}  ${x.p.artifacts.availability.padEnd(22)} ${linkOf(x.p.artifacts)}`);
  
 // --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
 +// ---------------------------------------------------------------------------
 +// 6b. Two probes the page cites in footnotes. Both were added on 2026-09-13
 +//     after review found the page asserting negatives no probe supported.
 +// ---------------------------------------------------------------------------
 +H('6b. TWO PROBES THE PAGE CITES');
 +
 +// (i) The TLS decryption hole. The page originally ran only NARROW, matched 1
 +//     of 13 Tier A papers, and published "almost nobody reports the hole" —
 +//     while quoting two of the sentences NARROW misses. A narrowing probe must
 +//     return a SUBSET of the loose one; both counts are printed so the claim
 +//     can be read off the right width.
 +const HOLE_NARROW = /could not decrypt|failed to decrypt|decryption fail|unable to (decrypt|intercept)/i;
 +const HOLE_WIDE = new RegExp([
 +  /(could not|cannot|can ?not|unable to|failed to|no way to)[^.]{0,90}(decrypt|intercept|install (our own |a |custom )?(self-signed )?certificat)/.source,
 +  /(bypass|remove|disabl\w*)[^.]{0,40}certificate pinning/.source,
 +  /certificate pinning checks/.source,
 +].join('|'), 'i');
 +const holeN = A.filter((x) => HOLE_NARROW.test(fulltext(x.p)));
 +const holeW = A.filter((x) => HOLE_WIDE.test(fulltext(x.p)));
 +const holeNs = new Set(holeN.map((x) => x.p.slug));
 +const notContained = holeN.filter((x) => !holeW.some((y) => y.p.slug === x.p.slug));
 +if (notContained.length)
 +  throw new Error(`the narrow decryption probe is not a subset of the wide one: ${notContained.map((x) => x.p.slug).join(', ')}`);
 +if (holeN.length > holeW.length)
 +  throw new Error(`narrow probe matched ${holeN.length} > wide ${holeW.length}; a narrowing probe must match fewer`);
 +console.log(`TLS decryption hole, Tier A (n=${A.length}):`);
 +console.log(`  narrow probe (the one the page published until 2026-09-13): ${holeN.length}`);
 +console.log(`  wide probe   (the one the page cites now)                 : ${holeW.length}`);
 +for (const x of holeW) {
 +  const t = fulltext(x.p), m = t.match(HOLE_WIDE), i = t.indexOf(m[0]);
 +  console.log(`   ${holeNs.has(x.p.slug) ? 'both  ' : 'wide  '} ${x.p.venue} ${x.p.year} ${x.p.slug}`);
 +  console.log(`          ...${t.slice(Math.max(0, i - 100), i + 200)}...`);
 +}
 +
 +// (ii) ATSC 3.0 / NextGen TV. The page says no paper measures it. That was an
 +//      unprobed negative until now; ATSC was never in PROBES.
 +const ATSC = /\bATSC\b|\bNextGen ?TV\b|\bNext ?Gen ?TV\b/i;
 +const atscHits = ALL.filter((p) => ATSC.test(fulltext(p)));
 +console.log(`\nATSC 3.0 / NextGen TV, full text, all ${ALL.length} corpus papers: ${atscHits.length} match`);
 +for (const p of atscHits) {
 +  const t = fulltext(p), m = t.match(ATSC), i = t.indexOf(m[0]);
 +  console.log(`   ${p.venue} ${p.year} ${p.slug}   [${MAP[p.slug] ? MAP[p.slug][0] : 'not in audit set'}]`);
 +  console.log(`          ...${t.slice(Math.max(0, i - 130), i + 210)}...`);
 +}
 +
 +// (iii) The factory-reset gap. crawlConfig.statefulness is empty for all 6
 +//       papers that have the object; the page needed the full-text picture too.
 +const RESET = /factory[- ]reset/i;
 +const resetHits = POP.filter((x) => RESET.test(fulltext(x.p)));
 +const withCfg = POP.filter((x) => x.p.crawlConfig !== null);
 +console.log(`\nStatefulness: ${withCfg.length} of ${nPOP} papers have a crawlConfig object;`);
 +console.log(`  statefulness values among them: ${JSON.stringify(withCfg.map((x) => x.p.crawlConfig.statefulness))}`);
 +console.log(`  full-text "factory reset" anywhere in the ${nPOP}: ${resetHits.length}`);
 +for (const x of resetHits) {
 +  const t = fulltext(x.p), i = t.search(RESET);
 +  console.log(`   ${MAP[x.p.slug][0]}  ${x.p.venue} ${x.p.year} ${x.p.slug}`);
 +  console.log(`          ...${t.slice(Math.max(0, i - 130), i + 210)}...`);
 +}
 +
 +// (iv) LLM use inside the population. The page said "not one paper uses an LLM
 +//      for anything"; two do, and both tool names are in the printed residue.
 +console.log('\nLLM and language-model tools used by the population (tools[].category, used only):');
 +for (const x of POP) {
 +  for (const t of x.p.tools) {
 +    if (t.usedOrMentioned !== 'used') continue;
 +    if (!/^llm$/i.test(t.category) && !/gpt|openai|chatgpt|bert|language model/i.test(t.name)) continue;
 +    console.log(`   ${x.p.venue} ${x.p.year}  category=${t.category.padEnd(22)} ${t.name}`);
 +    console.log(`          quote: ${JSON.stringify((t.evidence?.quote || '').slice(0, 200))}`);
 +  }
 +}
 +
 // 7. Quote verification lives in scripts/ctv_quotecheck.py, which checks each // 7. Quote verification lives in scripts/ctv_quotecheck.py, which checks each
 //    quote against BOTH paper.cols.txt and the PDF text layer. Doing it here //    quote against BOTH paper.cols.txt and the PDF text layer. Doing it here
Line 999: Line 1235:
     ('2019', 'USENIX', 'all-things-considered-an-analysis-of-iot-devices-on-home-networks',     ('2019', 'USENIX', 'all-things-considered-an-analysis-of-iot-devices-on-home-networks',
      'are the most common type of device in seven of the eleven regions'),      'are the most common type of device in seven of the eleven regions'),
 +    # --- added 2026-09-13, for claims the round-2 review changed -------------
 +    # The widened TLS-decryption probe: the three Tier A sentences the page now
 +    # quotes. The narrow probe matched only the second of these, which is how a
 +    # "1 of 13" reached the page while two of the three sat in its own prose.
 +    ('2019', 'CCS', 'watching-you-watch-the-tracking-ecosystem-of-over-the-top-tv-streaming-devices',
 +     'to bypass certificate pinning'),
 +    ('2020', 'PETS', 'the-tv-is-smart-and-full-of-trackers-measuring-smart-tv-advertising-and-tracking',
 +     'we cannot install our own self-signed certificates on the Roku'),
 +    ('2022', 'PETS', 'watch-over-your-tv-a-security-and-privacy-analysis-of-the-android-tv-ecosystem',
 +     'there is no way to install custom certificates on Android TV'),
 +    # The factory-reset sentence. In .cols this one is SPLICED by the
 +    # de-columner — "and the UT-We perform a factory reset of the TV for each
 +    # channel analysis 100c HiDes modulator" — so only the first clause is
 +    # contiguous there. The PDF layer carries the whole sentence.
 +    ('2023', 'NDSS', 'i-still-know-what-you-watched-last-sunday-privacy-of-the-hbbtv-protocol-in-the-european-smart-tv-landscape',
 +     'We perform a factory reset of the TV for each channel analysis'),
 +    # AndroZoo: the page said every TV-app paper built its own set.
 +    ('2022', 'PETS', 'watch-over-your-tv-a-security-and-privacy-analysis-of-the-android-tv-ecosystem',
 +     'download the last version of each app (as of August 2020) from AndroZoo'),
 +    ('2023', 'IMC', 'in-the-room-where-it-happens-characterizing-local-communication-and-threats-in-s',
 +     'we randomly selected 1.5K unique package names from Androzoo'),
 +    # The one real ATSC mention in the whole 5,859-paper corpus.
 +    ('2014', 'USENIX', 'from-the-aether-to-the-ethernet-attacking-the-internet-using-broadcast-digital-t',
 +     'published a candidate standard for hybrid TV in America'),
 +    # Both sides of the opt-out: the paper the page had omitted.
 +    ('2019', 'CCS', 'watching-you-watch-the-tracking-ecosystem-of-over-the-top-tv-streaming-devices',
 +     'this time enabling the "Limit Ad Tracking" (Roku) and the "Disable Interest-based Ads" (Amazon Fire TV) settings'),
 ] ]
  
Line 1461: Line 1724:
 not-stated                 4 not-stated                 4
 stratified                 3 stratified                 3
-paper        iot-devices n values stated +paper                                               iot-devices n values stated 
------------  --------------------------- +--------------------------------------------------  --------------------------- 
-IMC 2011     7000000, 140000 +IMC 2011 q-score-proactive-service-quality-asse     7000000, 140000 
-PETS 2020    57 +PETS 2020 the-tv-is-smart-and-full-of-trackers-m    57 
-USENIX 2021  11 +USENIX 2021 android-smarttvs-vulnerability-discove  11 
-IMC 2024     2 +IMC 2024 watching-tv-with-the-second-party-a-fi     2 
-IMC 2019     81 +IMC 2019 information-exposure-from-consumer-iot     81 
-USENIX 2019  83000000, 500000, 1000 +USENIX 2019 all-things-considered-an-analysis-of-i  83000000, 500000, 1000 
-IMC 2020     96 +IMC 2020 a-haystack-full-of-needles-scalable-de     96 
-NDSS 2020    19, 55, 26, 45 +NDSS 2020 packet-level-signatures-for-smart-home    19, 55, 26, 45 
-NDSS 2020    31 +NDSS 2020 et-tu-alexa-when-commodity-wifi-device    31 
-USENIX 2020  31850, 423, 26478 +USENIX 2020 you-are-what-you-broadcast-identificat  31850, 423, 26478 
-IMC 2021     40 +IMC 2021 iotls-understanding-tls-usage-in-consu     40 
-PETS 2021    31 +PETS 2021 blocking-without-breaking-identificati    31 
-PETS 2022    45, 28, 18, 70, 19, 8 +PETS 2022 analyzing-the-feasibility-and-generali    45, 28, 18, 70, 19, 8 
-USENIX 2022  44 +USENIX 2022 lumos-identifying-and-localizing-diver  44 
-IMC 2023     2014, 113, 7 +IMC 2023 behind-the-scenes-uncovering-tls-and-s     2014, 113, 7 
-IMC 2023     93, 13487 +IMC 2023 in-the-room-where-it-happens-character     93, 13487 
-IMC 2024     93 +IMC 2024 iot-bricks-over-v6-understanding-ipv6-     93 
-PETS 2024    25123, 54950, 30, 66 +PETS 2024 connecting-the-dots-tracing-data-endpo    25123, 54950, 30, 66 
-NDSS 2025    90 +NDSS 2025 evaluating-machine-learning-based-iot-    90 
-NDSS 2026    22+NDSS 2026 blerp-ble-re-pairing-attacks-and-defen    22 
 + 
 +papers stating an iot-devices size : 20 of 35 
 +stated size values                : 39 
 +all values, sorted                : 2, 7, 8, 11, 18, 19, 19, 22, 26, 28, 30, 31, 31, 40, 44, 45, 45, 55, 57, 66, 70, 81, 90, 93, 93, 96, 113, 423, 1000, 2014, 13487, 25123, 26478, 31850, 54950, 140000, 500000, 7000000, 83000000 
 +median of all stated values       : 66 
 +largest set per paper, sorted     : 2, 11, 22, 31, 31, 40, 44, 55, 57, 70, 81, 90, 93, 96, 2014, 13487, 31850, 54950, 7000000, 83000000 
 +median of largest-per-paper       : 75.5 
 +papers whose LARGEST set <=  100   : 14 of 20 
 +papers whose LARGEST set <=  200   : 14 of 20 
 +papers whose LARGEST set <= 1000   : 14 of 20 
 +papers whose largest set is over 200, i.e. not a lab bench: 
 +  IMC 2011 q-score-proactive-service-quality-asse  -> 7000000, 140000 
 +  USENIX 2019 all-things-considered-an-analysis-of-i  -> 83000000, 500000, 1000 
 +  USENIX 2020 you-are-what-you-broadcast-identificat  -> 31850, 423, 26478 
 +  IMC 2023 behind-the-scenes-uncovering-tls-and-s  -> 2014, 113, 7 
 +  IMC 2023 in-the-room-where-it-happens-character  -> 93, 13487 
 +  PETS 2024 connecting-the-dots-tracing-data-endpo  -> 25123, 54950, 30, 66
  
 population tuples in A+B stating a listVersion: 42 of 105 population tuples in A+B stating a listVersion: 42 of 105
Line 1887: Line 2167:
   IMC 2011  public                 www.research.att.com/∼kkrama/papers/streamcontrol.pdf   IMC 2011  public                 www.research.att.com/∼kkrama/papers/streamcontrol.pdf
   IMC 2011  (no artifacts object extracted)   IMC 2011  (no artifacts object extracted)
-  USENIX 2014  none-mentioned         [object Object]+  USENIX 2014  none-mentioned         http://www.avalpa.com/the-key-values/15-free-software/33-opencaster  (other; OpenCaster software; authors=false)
   CCS 2019  promised-not-yet-available —   CCS 2019  promised-not-yet-available —
-  PETS 2020  promised-not-yet-available [object Object] +  PETS 2020  promised-not-yet-available http://athinagroup.eng.uci.edu/projects/smarttv/  (project-page; Project page for tools and testbed datasets; authors=true) 
-  USENIX 2021  none-mentioned         [object Object]+  USENIX 2021  none-mentioned         https://sites.google.com/site/smarttvdemos/  (project-page; Demonstration website for discovered attacks; authors=true)
   PETS 2022  promised-not-yet-available https://github.com/UCI-Networking-Group/fingerprintv   PETS 2022  promised-not-yet-available https://github.com/UCI-Networking-Group/fingerprintv
   PETS 2022  public                 https://gitlab.com/s3lab-rhul/watch-over-your-tv-paper   PETS 2022  public                 https://gitlab.com/s3lab-rhul/watch-over-your-tv-paper
Line 1898: Line 2178:
   NDSS 2024  public                 https://github.com/tejaskannan/smart-tv-keyboard-leakage   NDSS 2024  public                 https://github.com/tejaskannan/smart-tv-keyboard-leakage
   USENIX 2025  restricted             https://doi.org/10.5281/zenodo.15646588   USENIX 2025  restricted             https://doi.org/10.5281/zenodo.15646588
 +
 +==============================================================================
 +6b. TWO PROBES THE PAGE CITES
 +==============================================================================
 +TLS decryption hole, Tier A (n=13):
 +  narrow probe (the one the page published until 2026-09-13): 1
 +  wide probe   (the one the page cites now)                 : 3
 +   wide   CCS 2019 watching-you-watch-the-tracking-ecosystem-of-over-the-top-tv-streaming-devices
 +          ...tificate to the device and use external toolkits (e.g., Frida [29] for the Amazon Fire Stick TV) to bypass certificate pinning. Contributions: We make the following contributions: • We conduct the first large-scale study of privacy practices of OTT streaming channels. Using an automated crawler that...
 +   both   PETS 2020 the-tv-is-smart-and-full-of-trackers-measuring-smart-tv-advertising-and-tracking
 +          ...tion time with each app is approximately 16 minutes. We do not attempt to decrypt TLS traffic as we cannot install our own self-signed certificates on the Roku. 4.2 Fire TV Data Collection In this section, we describe the Fire TV platform, our app selection methodology, and present an overview of Fi...
 +   wide   PETS 2022 watch-over-your-tv-a-security-and-privacy-analysis-of-the-android-tv-ecosystem
 +          ...k traffic. We instrumented the APKs using the mitm-proxy script [32] to add Charles certificate and remove certificate pinning checks. This instrumentation is only necessary for TV apps as there is no way to install custom certificates on Android TV. For the mobile apps, we use smartphones with Andr...
 +
 +ATSC 3.0 / NextGen TV, full text, all 5859 corpus papers: 4 match
 +   USENIX 2012 i-forgot-your-password-randomness-attacks-against-php-applications   [not in audit set]
 +          ...mber of bits truncated. Application Attack Application Attack mediawiki 4.2 4.3 5.3 • Joomla 4.3 • Open eClass 4.2 4.3 5.4 • MyBB ATSc 4.1c 5.3c ◦ taskfreak 4.2 4.3 5.3 • IpBoard ATSc 4.1c 4.2c • zen-cart ATS RT • phorum 4.2 4.3 5.3 • osCommerce 2.x ATS RT • HotCRP 4.2 4.3 5.3 • osCommerce 3.x 4.2 4.3 5.4 • gazelle 4.3 5.3 • elgg ATSc 4.2...
 +   USENIX 2014 from-the-aether-to-the-ethernet-attacking-the-internet-using-broadcast-digital-t   [A]
 +          ...ctive deployment or in advanced stages of testing in most of Europe. In December 2013, the Advanced Television Systems Committee (ATSC), which defines the digital video standards in the US, Canada, South Korea and several USENIX Association other countries, published a candidate standard for hybrid TV in America [6]. This candidate standa...
 +   NDSS 2020 automated-cross-platform-reverse-engineering-of-can-bus-commands-from-mobile-apps   [not in audit set]
 +          ...E, ATA, ATH... Gauged 17 ATED, ATD, ATP, ATZ... iOBD2 20 ATE, AT ST, AT CA F... LeagendOBD 12 ATE, ATB, ATTR, ATQ... Engie 8 ATE, ATSC, ATI, ATST... TABLE X: AT commands extracted from dongle apps. 16 App # Command AcuraLink 9 Alpine 2 Alpine Tunelt 3 Audi MMI Connect 10 Carbin Control 15 Car-Net 4 Companion 2 Mini Connected Classic 1 Nis...
 +   CCS 2025 dont-look-up-there-are-sensitive-internal-links-in-the-clear-on-geo-satellites   [not in audit set]
 +          ...ngel Electronics. 2024. STAB HH90 Satellite Dish Motor. https:// angelelectronics.ca/products/stab-hh90-satellite-dish-motor. [8] ATSC. [n. d.]. ATSC. https://www.atsc.org/documents/. [9] Robin Bisping, Johannes Willbold, Martin Strohmeier, and Vincent Lenders. 2024. Wireless Signal Injection Attacks on VSAT Satellite Modems. USENIX Secur...
 +
 +Statefulness: 6 of 35 papers have a crawlConfig object;
 +  statefulness values among them: ["not-stated","not-stated","not-stated","not-stated","not-stated","not-stated"]
 +  full-text "factory reset" anywhere in the 35: 2
 +    NDSS 2023 i-still-know-what-you-watched-last-sunday-privacy-of-the-hbbtv-protocol-in-the-european-smart-tv-landscape
 +          .... For the second test, we start by extracting the HbbTV URLs from the DVB stream using the TSDuck library and the UT-We perform a factory reset of the TV for each channel analysis 100c HiDes modulator. As mentioned in Section II, the DVB to prevent interference in the captured traffic. stream includes the URLs of the HbbTV applications; t...
 +    NDSS 2026 blerp-ble-re-pairing-attacks-and-defenses
 +          ... introduces a usability trade-off: if a device implicit authentication, ensuring that an attacker lacking loses its PK (e.g., via factory reset), it requires manual user the current PK cannot compute the new one. intervention to re-pair. • Transcript Hashing: Devices must maintain a cumulative We implemented this protocol in NimBLE by ext...
 +
 +LLM and language-model tools used by the population (tools[].category, used only):
 +   CCS 2022  category=ml-model-or-algorithm  BERT
 +          quote: "IoTSpotter's BERT-based and BiLSTM classifiers identified 58,859 and 69,270 app descriptions as mobile-IoT, respectively."
 +   IMC 2023  category=llm                    ChatGPT (OpenAI's TextCompletion API)
 +          quote: "Using OpenAI's TextCompletion API, we develop prompt to infer device vendors and categories based on DHCP hostname, mDNS/SSDP responses, and user labels."
 +   PETS 2024  category=llm                    OpenAI Text Completion API
 +          quote: "Using OpenAI's Text Completion API [34], we develop prompts to infer device vendors and categories"
 +   PETS 2024  category=ml-model-or-algorithm  PrivBERT
 +          quote: "We use PrivBERT [69], a pre-trained privacy policy language model to build a binary classifier"
  
 ============================================================================== ==============================================================================
Line 1906: Line 2227:
 ===== 14. Run log ===== ===== 14. Run log =====
  
-  * **2026-09-12** — page written. Corpus ''data/extract/run1'', 5,859 papers. Candidate pool, audit, report script, quote check, bibliography generation and external verification all run on this date. +  * **2026-09-12** — page written. Corpus ''data/extract/run1'', 5,859 papers. Candidate pool, audit, report script, quote check, bibliography generation and external verification all run on this date. Three review passes — figures-versus-script, citations-and-quotes and external currency — returned and were applied; they are logged in §15. A fourth, generic pass was still running when the session ended, so it is **not** in §15. An earlier version of this line said all four were logged there; that was wrong. 
-  * Sub-agents: four review passes — figures-versus-script, citations-and-quotesexternal currencyand generic pass — logged in §15 with every finding and whether it was accepted+  * **2026-09-13** — round 2. All four passes re-run against the published pages, because every focused domain had been changed by round 1's own fixes. 21 findings accepted, 3 rejected, logged in §15b. Two of round 1's accepted fixes turned out to be wrong and one had landed on only one of the two pages. The report script gained membership and topic digests (§5b), a ''linkOf()'' helper, and three probes the page had been citing without having: the wide TLS-decryption probe, the ATSC full-text probe and the factory-reset probe. Section §13 is regenerated from the current script. 
-  * No credential or token was printed at any point in this run.+  * Models: the three focused passes were ''sonnet'', the generic pass was ''fable'', in both rounds. The generic pass found more real defects in round 2 than the three focused passes combined — see the closing note in §15b for why that is structural rather than luck
 +  * No credential or token was printed at any point in either run.
  
 ===== 15. Review log ===== ===== 15. Review log =====
  
-(pending — filled in after the review passes complete.)+Three review passes returned on 2026-09-12 against the published pages, the report script and its output; the fourth was cut off mid-run and was re-run as part of round 2 (§15b). Each was told explicitly that the author's context might not be exhaustive and to verify rather than assume. **Every finding below was re-checked by hand against the primary source before it was accepted or rejected** — two of the accepted ones needed correcting in the process, and the rejections are recorded because they are the only evidence of whether a reviewer earned its slot. 
 + 
 +==== Round 1, pass 1 — figures versus script (sonnet) ==== 
 + 
 +^ # ^ Finding ^ Disposition ^ 
 +| 1.1 | The "fifteen IoT-device-set papers" list substitutes {[rye2024_surveilling]} (tagged ''device-population'') for the real fifteenth, //Et Tu Alexa?// (NDSS 2020), which is cited nowhere | **Accepted.** Independently confirmed by extracting the tier/topic tuples from ''ctv_fold.mjs''. Fixed: the list is now exactly the fifteen, {[zhu2020_alexa]} was added to the bibliography, and {[rye2024_surveilling]} is described in its own clause. This was also found independently by the author before the pass returned | 
 +| 1.2 | Both pages say the alias fold "maps 25 names"; it has **27 skeleton keys onto 22 canonical names** | **Accepted.** Re-parsed the ''ALIAS'' object: 27 and 22, neither of them 25. //This row originally read "Corrected on both pages". That was false:// only the content page was corrected in round 1. This provenance page still said 25 until round 2 found it — three separate reviewers, plus the author's own residue sweep, all landed on the same line. See §15b, finding R2.6 | 
 +| 1.3 | The sampling-size paragraph attributes "3,000,000 IPTV set-top boxes" to {[gopalakrishnan2011_couch]} as one of "the 20 papers stating an ''iot-devices'' population size", but that paper's tuples are unit ''other'' and ''human-participants''. The paper that //is// one of the 20 with large values, {[song2011_score]} (7,000,000 and 140,000), is named nowhere | **Accepted, and it was worse than reported.** The author had already flagged the same sentence for omitting 57 — the PETS 2020 testbed — from a hand-typed list; the reviewer found the framing error underneath it. The whole passage is now generated by the script (§13) rather than typed, and the 3,000,000 figure is kept with an explicit note that it is a subscriber count, not one of the 20 | 
 +| 1.4 | The map guard only checks the slug set. **Flipping a tier letter exits 0** and silently moves the population from 35 to 34 | **Accepted, and the most valuable finding of the round.** The reviewer mutation-tested rather than read. Fixed with a summing invariant; see §5b | 
 +| 1.5 | Committed output is byte-identical to a fresh run; venue split, platform distribution, "6 of 35 crawled", all three corpus comparison rows and the detection-prevalence coverage independently re-derived from ''extractions.jsonl'' and all matching; every checked row of //Measured results you can cite// correct against raw paper text; nullable-field denominators and paper-not-tuple counting correct | No action. Recorded because "I re-derived it without your script and it matched" is the check that matters | 
 +| 1.6 | Venue display labels differ between page ("USENIX Security", "TheWebConf") and script ("USENIX", "WWW") | **Rejected.** The page uses the venues' real names and the numbers underneath are identical. Cosmetic | 
 + 
 +==== Round 1, pass 2 — citations and quotes (sonnet) ==== 
 + 
 +^ # ^ Finding ^ Disposition ^ 
 +| 2.1 | The ATSC broadcaster-application quote is **altered** as well as misattributed: the source sentence reads "broadcasters can load and reload, //and change things as they are happening//, based on broadband availability…", and the page drops that clause without an ellipsis and inserts the word "content". The source is also a news article paraphrasing an unnamed speaker ("she said"), not ATSC, and not the URL cited | **Accepted, BLOCKER.** The author had independently confirmed the quote was on neither cited page; the reviewer established that it had also been silently edited. The quote is removed entirely rather than repaired — a secondhand paraphrase of an unnamed conference speaker is not a source this page should lean on. Replaced with what ATSC's own pages do say, a pointer to A/344, and the FCC proceeding | 
 +| 2.2 | Roku's functions are ''GetRIDA()'' and ''IsRIDADisabled()''; the page mis-capitalised both, and ''IsRIDADisabled()'' is documented on ''ifDeviceInfo'', not on the page cited | **Accepted.** Confirmed by fetching ''ifdeviceinfo.md'' directly. Both names corrected and both docs now cited | 
 +| 2.3 | All 33 citekeys resolve; no key defined twice in the merged 1,024-entry bibliography; 0 rule-A/B duplicates; the three rule-D candidates touching new keys are same-surname-different-author | No action | 
 +| 2.4 | **Author order for all 31 new entries checked against the papers' own PDF front matter, and the 18 DOI-bearing ones additionally against Crossref's order-sensitive author array.** All 31 correct, including the re-split "Al Aaraj, Jad" and {[ahmed2022_analyzing]}, whose title page has no text layer | No action. This is the check the author could not fully self-run, and it is the reason the pass was worth its slot | 
 +| 2.5 | Every other vendor, standards-body and regulator quote verified word-for-word from the primary source, including all four Texas dates and the "every 500 milliseconds" wording | No action | 
 +| 2.6 | The rendered DOM matches the source: 83 markers, 33 reference entries, 4 WRAP blocks, 16 tables, no truncation | No action | 
 +| 2.7 | The Tier-B rule is paraphrased two different ways on the same page ("…for a television" versus "…for them") | **Accepted** as a NIT. Wording made consistent | 
 + 
 +==== Round 1, pass 3 — external currency (sonnet) ==== 
 + 
 +^ # ^ Finding ^ Disposition ^ 
 +| 3.1 | The ATSC capability quote is on neither cited page; it is a 2016 conference paraphrase on a third URL | **Accepted** — the same defect as 2.1, found independently by a pass with a different brief. Two reviewers arriving at one finding from opposite directions is the strongest signal in this round | 
 +| 3.2 | The FCC's Fifth FNPRM (GN Docket 16-142, adopted 2025-10-28) on the ATSC 1.0 sunset is missing | **Accepted**, after fetching the FCC's own fact sheet rather than the trade coverage the reviewer cited. The primary document gave a better fact than the finding did: the simulcast rule "was extended to July 17, 2027", and the notice's list of outstanding issues includes a one-word bullet, "Privacy". Added | 
 +| 3.3 | Kentucky HB 692 classifies ACR data as sensitive data, effective 2027-07-01 | **Accepted with a correction.** That is the bill //as introduced//. The **enacted** version (Acts Chapter 118) instead "prohibit[s] controllers from collecting automatic content recognition data without a consumer's consent". Added in the enacted form, from the legislature's own record page | 
 +| 3.4 | Sony, Hisense and TCL remain unsettled; the timeline reads as if Samsung and LG were the whole story | **Accepted.** Added, together with the explicit negative result that no EU or UK regulatory action was found | 
 +| 3.5 | "ADB Wi-Fi 2.0" (Android 17) was announced 2026-09-09, three days before this page claimed currency | **Accepted on a different source.** The blog URL the reviewer gave returns 404. The primary ''adb'' documentation already states it, so the claim is added on that authority instead | 
 +| 3.6 | The Walmart press release contains neither "Platform+" nor "Inscape" | **Accepted.** Confirmed by text search. The footnote now supports only what the release says | 
 +| 3.7 | ''research.att.com/~kkrama/papers/streamcontrol.pdf'' (an extracted artifact URL) returns 403 | **Accepted** as a NIT; annotated rather than removed, since it records what the paper claimed. See §8 | 
 +| 3.8 | HbbTV 2.0.5, the ATSC 76% figure, Samsung TIFA, Amazon Fire TV, Roku ECP, the six regulatory dates, all five artifact repositories, the Zenodo DOI and mitmproxy v12.2.3 all verified live and correct | No action | 
 +| 3.9 | The HbbTV 2.0.5 paraphrase ("adding DRM and WebAssembly recognition") is looser than the source's "recognising features in the market such as DRM and WebAssembly" | **Rejected.** The substance is right and the rest of the sentence is near-verbatim | 
 +| 3.10 | Samsung's own TRO was granted and vacated the next day, before the February settlement | **Rejected** for the content page. Real, but a procedural detail; the substantive gap was 3.4, which is in | 
 + 
 +==== What round 1 cost and returned ==== 
 + 
 +Three passes returned; a fourth, the generic one, was still running when the session ended and is logged in §15b with round 2 insteadCounting the rows above: **14 accepted** (1.1–1.4, 2.1, 2.2, 2.7, 3.1–3.7), two of them accepted-with-correction, and **3 rejections** (1.6, 3.9, 3.10). An earlier version of this paragraph said "eleven accepted, four rejections", which does not match its own tables. The pattern worth recording for the next run: **the defects were all in prose that summarises data, never in the tables the script generates.** Every generated figure survived independent re-derivation; every hand-typed list, paraphrase and quotation that sat next to one had to be fixed. The two most valuable findings — the mutation test that broke the guard, and the author-order check against Crossref — were both things that cannot be done by reading, which is the argument for handing a reviewer the script rather than only the page. 
 + 
 +====== References ====== 
 + 
 +The same keys and the same shared bibliography as [[design:connected_tv]]; this page adds no entries of its own. No discussion block: comments belong on the content page. 
 + 
 +===== 15b. Review log, round 2 (2026-09-13) ===== 
 + 
 +Round 1 ran three focused passes and was cut off with the generic pass still in flight. Round 2 re-ran **all four**, because every one of the three focused domains had been changed by round 1's own fixes — and that turned out to be the right call twice over: two of round 1's accepted fixes were themselves wrong, and a third had landed on only one of the two pages. Every reviewer was told the author's context might not be exhaustive. **Every finding below was re-checked by hand against the primary source or the raw corpus before being accepted or rejected.** 
 + 
 +The headline of this round: **the generic pass, which has no checklist, found more real defects than the three focused passes combined** — and all of them were claims about what the literature does //not// do. A reviewer asked to check figures against a script checks the figures that are in the script. A negative claim has no figure. 
 + 
 +==== Round 2, pass 1 — figures versus script (sonnet) ==== 
 + 
 +^ # ^ Finding ^ Disposition ^ 
 +| R2.1 | **The round-1 invariant can be satisfied vacuously.** Swapping two papers between tiers — one genuine Tier B out, one genuine ''OUT'' in — leaves ''A:13, B:22, ADJ:16, OUT:52'' unchanged and exits 0, while platform ''web'' goes 1→2 and the venue, year and platform tables all move | **Accepted, BLOCKER, and the most valuable finding of either round.** Reproduced exactly. §5b now records it, and membership is pinned per tier as a slug-list digest. **The pattern worth keeping: round 1's fix was written from the failure a reviewer demonstrated, and closed exactly that failure and nothing beside it.** It took a second mutation test, from a reviewer with the same brief, to find the hole next door | 
 +| R2.2 | ''artifacts.links[0]'' is an **object**, so the fallback printed the literal ''[object Object]'' — published three times in §13 | **Accepted.** Confirmed against ''extractions.jsonl''. Fixed with a ''linkOf()'' helper that takes ''.url'' and throws if the shape is ever a string; the three entries now carry real links, one of which (''athinagroup.eng.uci.edu/projects/smarttv/'') is a citable project page that had been hidden behind the bug | 
 +| R2.3 | Q16 says "33 empirical"; ''isEmpirical'' is true for **34** of the 35, and 27/34 is the 79.4% printed beside it | **Accepted.** Re-derived: exactly one paper (//Lumos//) is not empirical. Corrected | 
 +| R2.4 | The round-1 rewrite of the 3,000,000 IPTV figure says the paper "records them as subscribers"; the paper says "the average number of **set-top boxes** provisioned was approximately 3 million" | **Accepted — a round-1 fix that introduced a new error.** Verified in ''paper.cols.txt''. The real reason it is outside the 20 is that its extraction ''unit'' is ''other'', not ''iot-devices'' — a taxonomy boundary, not anything the paper did. The page now says that | 
 +| R2.5 | The ''topic'' tag has no invariant at all; changing one exits 0 and silently moves the "What this literature measures" table and the ''iot-device-set'' list | **Accepted.** Pinned with its own digest. Mutation-tested: it now throws | 
 +| R2.6 | The provenance page still says the alias fold maps "25 skeletons" while listing 27 of them | **Accepted.** Found independently by three of the four passes and by the author's own residue sweep. Corrected, and round 1's claim to have fixed "both pages" is corrected too | 
 +| R2.7 | Script reproduces byte-identically; the fifteen ''iot-device-set'' papers are exactly the fifteen named; venue, year, topic, platform, vantage, ''crawlConfig'', ethics and artifacts tables all match cell-for-cell; sentinels never counted as stated; papers never counted as tuples | No action. Recorded because it is the control | 
 + 
 +==== Round 2, pass 2 — citations and quotes (sonnet) ==== 
 + 
 +^ # ^ Finding ^ Disposition ^ 
 +| R2.8 | **"Nothing comparable was found from an EU or UK regulator" is false.** The UK ICO published a connected-TV programme on 2026-06-11 | **Accepted, BLOCKER.** Verified at ico.org.uk directly. See R2.11 — the other pass found the EU half independently | 
 +| R2.9 | Author order for ''zhu2020_alexa'' checked against the NDSS PDF front matter: Yanzi Zhu, Zhujun Xiao, Yuxin Chen, Zhijing Li, Max Liu, Ben Y. Zhao, Haitao Zheng — matches, no swap. All 34 citekeys resolve; 1,025 entries, 1,025 distinct keys; 0 rule-A/B duplicates | No action. This is the check the author cannot self-run, and it is why the pass earns its slot | 
 +| R2.10 | Every replacement claim from round 1 verified verbatim: the FCC's "extended to July 17, 2027" and its one-word "Privacy" bullet, Kentucky's enacted prohibition, ''GetRIDA()'' / ''IsRIDADisabled()'', the four Texas dates and the "every 500 milliseconds" quote, and the Texas AG's own statement that the cases against Sony, Hisense and TCL "remain ongoing" | No action | 
 + 
 +==== Round 2, pass 3 — external currency (sonnet) ==== 
 + 
 +^ # ^ Finding ^ Disposition ^ 
 +| R2.11 | **The EU half of the same blocker**: a joint Article 62 GDPR operation by the Dutch, Hungarian, Italian and Liechtenstein authorities published a final report on smart TVs on 2025-09-23 — a year before this page claimed the file was empty | **Accepted, BLOCKER.** Fetched and read the 14-page report. It is the single most useful external document on this page: **a regulator ran the measurement**, on three televisions, across first install, standby, off and ordinary use. Its off-state result (91–99% of flows to the OS provider) is now on the content page, and the fact that nobody in these seven venues has measured a television in the off state is now an open question. Neither European action uses the phrase "automatic content recognition", which is exactly why an ACR-shaped search could not see them | 
 +| R2.12 | **The round-1 Walmart fix is itself wrong** — the release does contain "VIZIO's Platform+ segment…"; the plus sign is HTML-entity-encoded, so a tag-strip search misses it | **Accepted — a second round-1 fix that introduced an error.** Reproduced: the string appears only after double entity-decoding. The footnote now quotes what the release says and records why the first check missed it. The reviewer flagged that its own first grep made the same mistake before its ''WebFetch'' caught it — an honest note that is worth more than a clean report | 
 +| R2.13 | The artifact table labels ''ahn2025_watch'' "restricted" while citing the DOI of the **open** record | **Accepted.** Zenodo's API says ''access_right: open''. The paper has two records; the label belongs to the other one. Both are now named | 
 +| R2.14 | FCC proceeding still pending, no Report and Order; HbbTV 2.0.5 still current; all five artifact repositories, the Zenodo DOI, mitmproxy v12.2.3 and every vendor doc re-verified | No action | 
 +| R2.15 | A trade-press claim that the FCC voted in May 2026 to mandate ATSC 3.0 tuners | **Rejected**, by the reviewer that surfaced it and again by the author: it appears nowhere on fcc.gov and the URL 403s. Recorded because this is the kind of claim that gets re-added | 
 +| R2.16 | One pass read the ATSC standards listing as showing A/344:2025-07 as the latest approved revision | **Rejected on better evidence.** The A/344:2026-04 PDF exists at HTTP 200 and its own title block reads ''A/344:2026-04 … 14 April 2026''. The document's own designation beats a reading of the listing page | 
 + 
 +==== Round 2, pass 4 — generic, no checklist (fable) ==== 
 + 
 +This pass found the cluster the other three could not, because **a false negative has no figure to check and no citation to verify**. Five claims about what the literature does not do were wrong, and two were refuted by the provenance page's own printed residue. 
 + 
 +^ # ^ Finding ^ Disposition ^ 
 +| R2.17 | "**LLM-based classification — Absent.** Not one paper in this population uses an LLM for anything." Two papers carry ''tools[]'' entries with ''category: llm'', ''used'' — and **both tool names are printed in this page's own residue block** | **Accepted, and the most embarrassing finding of the round.** {[girish2023_room]} and {[jakaria2024_dots]} both prompt OpenAI's Text Completion API to infer device vendor and category from DHCP hostnames. The claim is now the narrower and more useful one: an LLM is used here as a device-name resolver and has never been pointed at TV app metadata, store descriptions, ACR payloads or policies. **A residue you publish but do not read is not a control** | 
 +| R2.18 | "No paper states whether the device was factory-reset" was read off ''statefulness'' across the **6** papers that have a ''crawlConfig'' object and asserted over all **35**; {[tagliaro2023_still]} states it in so many words | **Accepted.** Classic denominator slip — the structured field is empty for the 6 that have it and silent for the other 29, which is not the same as those 29 saying nothing. A full-text probe is now in the script, and the page states both the field and the probe | 
 +| R2.19 | "**Exactly one paper** measures both sides of the opt-out." {[moghaddam2019_watching]} repeated its entire Roku and Fire TV crawl with "Limit Ad Tracking" and "Disable Interest-based Ads" enabled | **Accepted.** Two papers, five years apart, at different layers. Verified in both papers' own text | 
 +| R2.20 | "Almost nobody reports the hole — a probe matches **1** of 13" while the page **quotes two of the sentences the probe misses, three sections earlier** | **Accepted.** Probe width is a claim. The wide probe matches 3. The script now prints both widths and **asserts the narrow set is a subset of the wide one**, so a narrowing probe that returns more fails instead of publishing | 
 +| R2.21 | "There is no AndroZoo for TV apps… every paper built its own set." {[tileria2022_watch]}, the page's flagship TV-app paper, pulled its 4,745 APKs **from AndroZoo and APKMirror** | **Accepted.** The true statement is sharper: AndroZoo has no TV facet, so you cannot ask it for TV apps — you arrive with package names found elsewhere. For Roku, Tizen and webOS there is no archive at all | 
 +| R2.22 | The round-1 log claims four passes ran and that the generic one is "logged in §15 with every finding"; §15 logs three | **Accepted.** The generic pass was still running when the session ended. Corrected, and §15's own arithmetic (it said 11 accepted / 4 rejections against tables holding 14 and 3) corrected with it | 
 +| R2.23 | "The two vendors with the largest ACR businesses" is an unsourced market-size claim, and §10 says explicitly that installed-base share could not be established | **Accepted.** The two pages contradicted each other. Replaced with "two of the five vendors Texas sued", which is a fact on the record | 
 +| R2.24 | "Nobody has repeated…", "no TV paper has ever…", "Nobody has published…" — universal phrasing with no population, where the page elsewhere models the right form | **Accepted.** All three now name their population | 
 +| R2.25 | The lead says "the median TV study is a handful of physical devices"; the page's own medians are 66 and 75.5 | **Accepted.** The lead was describing the TV-specific papers while the median describes IoT testbeds. Both numbers are now given, with the distinction stated | 
 +| R2.26 | The table says fingerprintv is "promised, not yet available"; the prose two lines later counts "the five public repositories" | **Accepted.** The README still says the code "will be added… stay tuned", four years on, while the dataset is out. That is a better fact than either version, and it is now the row | 
 +| R2.27 | ''design:mobile_and_app_measurement'', ''privacy:requests'' and ''programming:filter_lists'' contain **no link back** to this page. A reader on the mobile page's pinning section has no signal that step 1 usually fails on a TV | **Accepted.** Reverse links added — see §16 | 
 +| R2.28 | ''\x27\x27sonnet\x27\x27'' in three §15 headings renders its own apostrophes, because DokuWiki headings ignore monospace markup | **Accepted.** Headings de-monospaced | 
 +| R2.29 | §5 reprints tables that §13 also carries in full (~150 duplicated lines) | **Rejected.** Deliberate, and stated as such: §5 is the readable verdict map and §13 is the unedited output. Someone checking a verdict should not have to scroll a 900-line block | 
 +| R2.30 | The page holds its stated boundaries in the outward direction, answers its own question, and the enforcement timeline belongs; rendered DOM matches source on both pages; 0 red links; both anchors resolve | No action. Recorded as the positive control | 
 + 
 +==== What round 2 cost and returned ==== 
 + 
 +Four passes, **21 accepted findings**, 3 rejections. Two of round 1's own accepted fixes were wrong (R2.4, R2.12) and one had landed on only one page (R2.6) — which is the argument for re-running a reviewer whose domain you changed, rather than trusting that a fix was a fix. 
 + 
 +Three things are worth carrying to the next page: 
 + 
 +  - **A negative claim is the least-guarded thing on a page.** Every figure here survived independent re-derivation, twice. Five of the six worst defects were sentences saying nobody does something, and none of the three focused briefs could have caught them — the checklist reviewer checks what is there. 
 +  - **A published residue must be read, not just printed.** The two LLM papers were in this page's own residue block, in plain sight, while the content page said they did not exist. 
 +  - **A fix closes the failure it was shown, and nothing next to it.** Round 1's invariant stopped a tier flip and let a tier swap through. The only thing that found the difference was mutating the code again, with the same brief, after the fix. 
 + 
 +===== 16. Reverse links added on 2026-09-13 ===== 
 + 
 +The round-2 generic pass checked the page's stated boundaries **in both directions** and found the outward direction good and the inward direction missing entirely: three pages this one defers to carried no link back, so a reader arriving at the neighbour had no signal that the TV case exists. 
 + 
 +^ Page ^ Where ^ What it now says ^ Revision ^ 
 +| [[design:mobile_and_app_measurement]] | head of //The Certificate-Pinning Problem// | a ''WRAP tip'' noting that the whole section assumes you can install a CA, which on Roku, Tizen and webOS you cannot, and on Android TV means instrumenting the APK instead | 1789266443 | 
 +| [[privacy:requests]] | Related pages | where this page's instruments stop: no interception without network-level capture, no page context to attribute a request to, filter-list coverage measured at 22–27% | 1789266444 | 
 +| [[programming:filter_lists]] | the existing **Smart TVs** coverage row | why the rule syntax itself does not transfer — no URL, no page context, no element hiding | 1789266446 | 
 + 
 +That page had previously pointed its smart-TV row at [[design:website_classification]], which is not where a reader chasing that 22% figure needs to go. 
 + 
 +<bibtex bibliography></bibtex>
  
provenance/design/connected_tv.1789234188.txt.gz · Last modified: by karel.kubicek.claude