User Tools

Site Tools


provenance:literature:corpus

Provenance: The Publication Corpus

Working log behind corpus. This page holds the working notes for that page's own figures; the corpus-level caveats every other provenance: page inherits — the venue scope, the funnel, the provisional years — are on corpus itself and are not restated here.

Its whole content, as of 2026-09-04, is one audit: the corpus-wide diff of an independent PDF rendering against the stored text renderings, which estimates what share of §6's 1.3% unlocatable-quote rate is a text-extraction artefact rather than an extraction defect. Estimates, not settles: it rests on one alternative PDF reader whose own failure rate is worse, and on a page-layout detector with no negative control. Both limits are in §7. corpus's other sections were written on 2026-08-12 with their notes inline, in its own §9 and §11; this page does not duplicate them.

1. Why this was run, and what it retracted

hypothesis_testing published, on 2026-08-13, that four of Mai et al.'s methodology quotes (PoPETs 2025, More and Scammier Ads) were present in the stored paper.pdf and in none of paper.cols.txt, paper.norm.txt or paper.txt, concluded that “the extraction was faithful; the stored rendering is deficient”, and logged a corpus-wide diff as the highest-value follow-up on that page.

The premise was wrong. Checked in Python on 2026-09-04, both sentences the content page quotes are in paper.cols.txt verbatim after the normalisation every checker on this site applies, and Friedman, Conover, omnibus, 172.47 and all ten authors are in all three renderings:

                                                        paper.txt  norm  cols
one-way repeated measures ANOVA as the omnibus test           no     no   YES
  since the ad load data follow a normal distribution
for the hypothesis on predatory ad rates, since the           no     no   YES
  rates do not approximately follow a normal
  distribution, we use Friedman test as the omnibus test
Friedman (7x) / Conover (6x) / omnibus / 172.47              yes    yes   yes
Kieserman / Matsumoto / Andreou / Greenstadt / McCoy         yes    yes   yes

The two full sentences are missing from paper.txt and paper.norm.txt for the ordinary reason: those renderings keep the columns side by side, so no sentence spanning a line is contiguous in them. That is the entire reason paper.cols.txt exists.

Why it was believed: the tool called ''grep'' here is not grep

pdftotext writes U+0000 wherever a PDF's font encoding maps a glyph to nothing. That paper's paper.cols.txt has 181 of them, so it is a binary file to any grep. What happens next depends on which grep, and the one you get by typing grep in this agent's shell is not the one installed on the machine:

$ type -a grep
grep is a shell function from /home/dev/.claude/shell-snapshots/snapshot-zsh-....sh
grep is /usr/bin/grep

$ typeset -f grep     # abridged
grep () { ...
  exec -a ugrep "$CLAUDE_CODE_EXECPATH" -G --ignore-files --hidden -I        --exclude-dir=.git ... "$@"
}

The agent harness installs a shell function that re-execs its own binary under the argv0 ugrep, with a fixed set of flags — and -I is one of them. -I means treat a binary file as containing no match. So on this file:

$ cd data/fulltext/2025/PETS/more-and-scammier-ads-.../
$ grep -c Friedman paper.cols.txt        # the function: no output, exit 1
$ grep    Friedman paper.cols.txt        # no output, exit 1
$ grep -o Friedman paper.cols.txt        # no output, exit 1
$ grep -a -c Friedman paper.cols.txt     # -a overrides the hardcoded -I
7

The real grep on this machine gets it right. /usr/bin/grep is GNU grep 3.8, it is not what the shell function runs, and it neither hides nor miscounts:

$ /usr/bin/grep --version | head -1
grep (GNU grep) 3.8
$ /usr/bin/grep -c Friedman paper.cols.txt
7
$ /usr/bin/grep Friedman paper.cols.txt
/usr/bin/grep: paper.cols.txt: binary file matches

So the trap is narrower and nastier than “grep hides binary matches”. It is: the grep an agent types is a wrapper with -I baked in, and no output plus exit 1 is indistinguishable from a real negative. It applies to the interactive shell an agent works in, not to the machine, and not to any script that shells out to grep itself — those get GNU grep 3.8. It was still enough to put a false finding on a published page.

1)

The exposure, from scripts/audit_binary_detect.mjs:

Rendering Files on disk Containing a NUL byte Share
paper.txt 5,859 90 1.5%
paper.norm.txt 5,859 90 1.5%
paper.cols.txt 5,855 90 1.5%

90 papers, 74,772 NUL bytes, and 2,156 of the 135,025 evidence quotes (1.6%) sit in them. They cluster in the recent years and in traffic-classification and ML papers — NDSS 35, WWW 20, CCS 15, IEEE S&P 10, USENIX 5, IMC 4, PoPETs 1; 2020 onwards holds 89 of the 90. None of this audit's scripts shell out to grep: they test for NUL with fs.readFileSync(f).includes(0) in process.

2. The scripts

Script What it does Cost
scripts/audit_cols_vs_pdf.py Renders every paper.pdf with pypdf, caches the text, and computes per-paper metrics: de-spaced character ratio, sentence recall, and a quote-by-quote replay 37 min, 2 workers, 5,859 PDFs; the cache is reused on any re-run, which then takes 190 s
scripts/audit_decolumn_pages.mjs Calls the real decolumn() on one page at a time to get that page's own verdict — reflowed, rejected, or left untouched — and scores each untouched page with a deliberately looser gutter detector 66 s
scripts/audit_page_geometry.py Ground truth: classifies a stratified sample of pages from the PDF's own text-positioning operators, with the reflowed pages as the control 28 s, 460 pages
scripts/audit_binary_detect.mjs Counts the renderings a shell grep lies about 10 s
scripts/report_cols_vs_pdf.mjs The outcome: every quote's verdict in both renderings, cross-tabulated 29 s
scripts/report_cols_mechanism.mjs The cause, and whether it predicts the outcome 0.1 s
scripts/pdftext.py The fallback the two quote checkers now call: one paper's PDF text, cached 0.5 s per paper
scripts/audit_quote_handcheck.py Prints one quote's neighbourhood in both renderings, for reading by hand instant
python3 scripts/audit_cols_vs_pdf.py --out out/colsaudit/per_paper.jsonl \
        --workers 2 --cache out/colsaudit/pdftext
node    scripts/audit_decolumn_pages.mjs --out out/colsaudit/per_page.jsonl
python3 scripts/audit_page_geometry.py --sample out/colsaudit/per_page.jsonl \
        --n 660 --out out/colsaudit/geometry_sample.jsonl
node    scripts/audit_binary_detect.mjs
node    scripts/report_cols_vs_pdf.mjs --examples 12 --both-fail 15
node    scripts/report_cols_mechanism.mjs

pdftotext is not installed in this container, so the stored paper.txt could not be regenerated and the comparison had to use a different reader rather than the same one. pypdf 6.16.2 was used — the current release on PyPI as of 2026-09-04. pdfminer, PyMuPDF, pdfplumber, mutool, qpdf and ghostscript are all absent too, so there is no third rendering and no majority vote: every “present in the PDF” verdict on this page rests on one reader.

pypdf refuses to decompress a stream over 75 MB and refuses an array-based stream whose parts total over 75 MB, and five of this corpus's PDFs are legitimately that large. On the first run that left 151 quotes with no second rendering. Both limits are raised in audit_cols_vs_pdf.py and pdftext.py:

import pypdf.filters as _f
_f.ZLIB_MAX_OUTPUT_LENGTH = 0                    # 0 disables, per its own docstring
_f.LZW_MAX_OUTPUT_LENGTH = 0
_f.RUN_LENGTH_MAX_OUTPUT_LENGTH = 10**12
_f.MAX_ARRAY_BASED_STREAM_OUTPUT_LENGTH = 10**12

Both constants are in pypdf.filters, including the array-based one. pypdf.generic._data_structures imports it from there at call time, so setting the name in _data_structures has no effect — which cost one wrong “still fails after raising the limit” conclusion during this run. With the raise, 5 of the 6 failures go away; the sixth needs the cryptography package, which pip refuses to install here under PEP 668 (see §8).

3. Every query, with its population and denominator

# Question Population Denominator Answer
Q1 Do the quotes the retracted section named exist in the stored renderings? one paper, PoPETs 2025 more-and-scammier-ads-… 4 quotes + 10 authors all present in paper.cols.txt; the retraction is Q0 of this page
Q2 How many stored renderings does a shell grep report nothing for? every extraction record 5,859 papers 90 (1.5%), holding 2,156 of 135,025 quotes
Q3 How many quotes does the stored rendering fail to locate? quotes with a verdict on both sides 135,004 quotes 1,708 (1.3%) — the same count report_corpus.mjs –quotes reports over all 135,025
Q4 How many of those does an independent PDF rendering find? the 1,708 1,708 quotes 1,250 (73.2%); 511 verbatim
Q5 How many quotes can neither rendering locate? the same 135,004 135,004 quotes 458 (0.34%)
Q6 How often is pypdf the worse reader? the same 135,004 135,004 quotes 2,662 (2.0%) found in the stored text and not in the PDF; pypdf's own not-found rate is 2.3% vs 1.3%
Q7 How many papers hold at least one rescued quote? every extraction record 5,859 papers 862 (14.7%)
Q8 How many pages did the two-column repair leave untouched? pages of every paper.txt 91,509 pages 29,347 (32.1%); 0 rejected by the word-multiset check
Q9 How many of those were really two-column? stratified sample, PDF geometry 400 untouched pages sampled, 60 reflowed as control est. 22,475 of 91,509 pages (24.6%, CI 21.5–26.6%)
Q10 Does the untouched-page rate predict the quote verdict? papers with ≥1 quote and both audits 5,853 papers yes, monotonically: exact 70.6% → 36.6%
Q11 Is any text actually lost, or only re-ordered? papers with both renderings 5,856 papers median de-spaced ratio 1.005; 34 papers (0.6%) below 0.95, of which 30 survive classification
Q12 Why do 4 records have no paper.cols.txt? records with no cols file 4 papers by design — no usable text layer, OCR-repaired into paper.mistral.md, which the extractor read
Q13 Which papers could not be rendered at all? every extraction record 5,859 papers 1 after the limit raise: NDSS/2025/mtzk-…, which needs the absent cryptography package. It holds 21 quotes

Denominators that are easy to mix up here. 135,025 is every evidence quote; 135,004 is the subset with a verdict on both sides, and the 21-quote difference is exactly the one paper that still cannot be rendered. 97,505 was the page count before the phantom trailing segment was removed; 91,509 is the real one. 5,859 is every record; 5,858 have a cached rendering, 5,856 have a comparable character count, 5,853 have both a quote and a page verdict. The 1,806 / 931 / 541 / 118 / 216 figures quoted from hypothesis_testing are hypothesis-test quotes only, scored by ht_quotecheck.mjs's much looser 60%-of-5-word-windows rule — not by the four-verdict rule everything else here uses, and not comparable to it.

4. The reproduction check that makes the rest usable

report_cols_vs_pdf.mjs does not approximate report_corpus.mjs –quotes: its four-verdict function is copied from it, including the fragmented anchor search. Run on the same day, on the same records:

Verdict report_corpus.mjs –quotes this audit Difference
exact 78,450 78,435 15
an 8-word run survives 49,425 49,419 6
fragmented 5,442 5,442 0
not found 1,708 1,708 0
total 135,025 135,004 21

15 + 6 + 0 + 0 = 21, the quotes in the one paper pypdf still cannot render. No quote changed bucket. Without that check the pdf column of every table below would be uninterpretable, because a difference could as easily be two verdict functions disagreeing as two renderings disagreeing.

5. Quotes read by hand

Six, with scripts/audit_quote_handcheck.py. All six are present in the paper; none is a fabrication.

Two different rules produce two different “rescued” populations, and mixing them up is easy. The four-verdict rule this page's tables use (exact / 8-word run / fragmented / not found) is the one report_corpus.mjs uses, and it is lenient: a spliced page usually keeps an 8-word run, so the quote still counts as located. quote_check.mjs and ht_quotecheck.mjs use a stricter per-page rule — 60% of the quote's 5-word windows — and a quote can be below that threshold while being comfortably run8 under the four-verdict rule. The last two rows below are of that second kind, and an earlier draft of this page labelled them as if they belonged to the 1,708. The citations-and-quotes reviewer caught it.

Paper Bucket What the stored rendering has
CCS/2010/a-methodology-for-empirical-analysis-of-permission-based-security-models… not found, exact in the PDF “applications can be assigned i to the nearest neuron, effectively clustering the applica-in our work, we employed euclidian distance as the distions requesting similar permissions into the same neightance metric, normalized to the range [0, 1]. borhood” — the two columns, line by line
CCS/2022/phishing-url-detection-a-network-based-approach-robust-to-evasion not found, exact in the PDF the page's table and two figure captions are spliced through the body text, so “We use Node2Vec [16] and DeepWalk [41].” survives only as “…phishy benign deepwalk and our network inference with…”
NDSS/2026/side-channel-inference-of-user-activities-in-ar-vr-using-gpu-profiling not found, run8 in the PDF “we employ workload remains high for a longer duration, resulting in linearregression from the python scikit-learn a broader width in the fingerprint created from non-base library [67] and separately compute pearson correlation level textures. Chosen because 2025–2026 hold the most not-found quotes, and corpus's own review criticised its five hand-checked examples for all being CCS 2010–2012
IMC/2011/pingin-in-the-rain neither rendering locates it present in both, matching neither. The stored text splices the columns; the PDF writes “(f aa)” and inserts a footnote marker “(asos) 3”; and the extraction wrote “Automated Surface Observation System” where the paper says “Observing”. A one-word paraphrase, not an invention — and a fair example of what the 458-quote residue is made of
CCS/2018/a-guided-approach-to-behavioral-authentication below the ht_quotecheck.mjs threshold (50%, and 100% in the PDF); run8 under the four-verdict rule, so not one of the 1,708 a table spliced into the running text: “they can be gnb rf lr policy interactive direction enforcement guidance used to augment security in combination with other”. “The Friedman test was adopted to determine the overall significant differences among three or more patterns” is verbatim in the PDF
NDSS/2026/chameleoscan-demystifying-and-detecting-ios-chameleon-apps… below the quote_check.mjs threshold; fragmented under the four-verdict rule, so not one of the 1,708 “appium [46] (via xcuitest) enabled comprehensive ui implicit instructions like "click the submit button 3 times to hierarchy analysis including hybrid-rendered components proceed," the system records the cue in the action history and (flutter and webview implementations)”

The examples printed by report_cols_vs_pdf.mjs are spread evenly through the corpus order, not the first N. The first twelve rescued quotes are all from 2010, for the same reason corpus's five were all from 2010–2012: the list is filled in sorted-key order. That is a property of the tool, and it produced a criticised sample once already.

audit_quote_handcheck.py tests exact containment only, so a quote whose PDF verdict is run8 or fragmented prints in pdf: False. Read the printed neighbourhood, not the boolean — the AR/VR and Chameleoscan rows above are both of that kind.

6. Normalisation, folding, and the residue printed in full

Nothing here is a free-text name fold, so there is no alias list. There are three normalisations, and each one hides something, so each is stated with what it hides.

Normalisation Why What it could hide
Whitespace collapsed, smart quotes folded, line-break hyphens joined — report_corpus.mjs's normText, copied the two renderings disagree about all three and none is content a quote that differs from the source only in whitespace is scored as verbatim. Deliberate; it is what every checker on this site does
fi/fl ligatures and the six dash codepoints folded, in the character-ratio comparison only pypdf and pdftotext emit different codepoints for the same glyph nothing that bears on a claim; the quote replay does not use this
Every character that is not [a-z0-9] dropped, in the character-ratio comparison only makes the ratio immune to pypdf's spurious intra-word spaces (“bo th”, “christop her”, “IS Ps in-volved” for “ISPs involved”), which are frequent word-order damage. It measures whether characters are present, never whether they are in the right order — which is why order is measured separately, by the sentence and quote tests
pypdf PostScript glyph names (/SolidCircle, /SolidUpTriangle) stripped from the PDF side one USENIX 2019 paper's scatter plots produced 473,591 characters of them (pdf_glyphname_chars in per_paper.jsonl) and made the stored rendering look 85.0% short a real /-prefixed token in a paper's text. Counted per paper before stripping, and the count is in per_paper.jsonl as pdf_glyphname_chars

The residue of the character-ratio comparison, in full. 34 of 5,856 papers fall below 0.95. Four are artefacts of the comparison — two whose extractor input was paper.mistral.md rather than paper.cols.txt (so the ratio compared a file nothing read), two where pypdf glyph names survived the strip because they are under the 10% threshold. The other 30 are listed in Appendix B and none was hand-read; they are candidates for real loss, they are 0.5% of the corpus, and the worst holds 58% of the PDF's characters rather than none of it.

Two residues that do not exist and should. The 458 quotes neither rendering locates are characterised from 12 read examples, not classified exhaustively. And the 31 sampled pages the geometry detector called too-little-text were not adjudicated at all — they are excluded from every share, which is the conservative direction for the 0.0–0.1 band and the anti-conservative direction nowhere.

7. What could not be established

  • Whether the 458 quotes neither rendering locates are all present in their papers. The 12 the report prints were read as text — the pattern is ellipsis splices the extraction marked itself, reflowed table rows, small capitals ("S ABOT"), symbol runs, sentences about a paper's silence, and one one-word paraphrase — but only one of them (IMC/2011/pingin-in-the-rain, §5) was checked against its paper. The other 457 were not opened. 0.34% is a ceiling on unlocatable, not a fabrication rate, and the true fabrication rate is not measured by this audit or by any other on this site.
  • Whether re-rendering would actually fix it. The obvious repair — lower the 50% vote threshold in findGutter, or replace it with the x-histogram test used here for ground truth — was not implemented and not tested. The dataset is mounted read-only in this container, so it could not be tried end to end, and a threshold change has a failure mode in the other direction: reflowing a genuinely single-column page shuffles it. The 60-of-60 control says the current detector has no false positives to lose, which is an argument for trying, not a measurement of trying. Filed as a task against the dataset repository rather than left here.
  • The geometry detector has no negative control. It is 60 for 60 on pages decolumn.mjs reflowed, which bounds its false negatives. Nothing bounds its false positives: no set of known single-column pages was assembled and put through it. If it over-calls two-column, the 22,475 estimate is too high, and the 0.6–1.0 band's unexplained 47.5% is the shape that would suggest. This is the weakest link in that number.
  • Whether a third reader would agree with pypdf. pdftotext, pdfminer, PyMuPDF, pdfplumber, mutool, qpdf and ghostscript are all absent from this container. Every “present in the PDF” verdict rests on one reader whose own not-found rate (2.3%) is worse than the rendering it audits (1.3%). The 73.2% is a lower bound in one sense — a better reader would rescue more — and unreplicated in another.
  • One paper still has no second rendering. NDSS/2025/mtzk-testing-and-exploring-bugs-in-zero-knowledge-zk-compilers uses AES encryption, so pypdf needs the cryptography package. pip install cryptography is refused here by PEP 668, and –break-system-packages was declined rather than risk the container for one paper's 21 quotes. Anyone with a normal Python environment can close this in one command.
  • The 57 pages that already publish a per-page quote-check figure. Each was computed against the stored rendering alone and each overstates its failure rate. They were not re-run; only hypothesis_testing was, because its own figures prompted the audit. The list, so the next editor does not re-derive it, is every page matching quote_check | quotecheck | below threshold | five-word windows | 5-word windows over a fresh export: design:website:classification, privacy:fingerprinting, privacy:tcf:consent:strings, programming:crawler, programming:crawler:detection, programming:crawler:foxhound, programming:crawler:llm:agents, programming:crawler:pagegraph, programming:crawler:panoptichrome, programming:crawler:webxray, provenance:artifacts, provenance:design:archives, provenance:design:existing:datasets, provenance:design:ip:classification, provenance:design:longitudinal, provenance:design:mobile:and:app:measurement, provenance:design:platforms, provenance:design:website:classification, provenance:practices:ethics, provenance:practices:legal:enforcement, provenance:privacy:ads:txt, provenance:privacy:browser:extensions, provenance:privacy:browser:protection, provenance:privacy:browser:storage, provenance:privacy:consent, provenance:privacy:cookie:syncing, provenance:privacy:email:tracking, provenance:privacy:fingerprinting, provenance:privacy:javascript, provenance:privacy:privacy:sandbox, provenance:privacy:server:side:tracking, provenance:privacy:tcf:consent:strings, provenance:programming:crawler, provenance:programming:crawler:detection, provenance:programming:crawler:foxhound, provenance:programming:crawler:llm:agents, provenance:programming:crawler:openwpm, provenance:programming:crawler:pagegraph, provenance:programming:crawler:panoptichrome, provenance:programming:crawler:webxray, provenance:programming:interaction, provenance:programming:interaction:outputs, provenance:programming:stateful:stateless, provenance:programming:traffic:files, provenance:programming:tranco, provenance:security:tls:certificates, provenance:security:web:vulnerabilities, provenance:statistics:biases, provenance:statistics:how:many:sites, provenance:statistics:hypothesis:testing, provenance:statistics:pvalue:corrections, provenance:statistics:regression, security:tls:certificates, statistics:biases, statistics:hypothesis:testing, statistics:pvalue:corrections, statistics:regression. Filed as deferred work rather than left as a note here.
  • Field stability. Still measured only on the 4,322-paper corpus, still not re-measured, and untouched by this audit.
  • Four other pages carry a lowercase <wrap> box, found while fixing the one on hypothesis_testing: provenance:practices:ethics, provenance:practices:notifying_websites, provenance:practices:public_relations and provenance:statistics:pvalue_corrections. Each renders its box as a <span> full of literal asterisks. Not fixed here — a different job from this audit, and filed as such. 2)

8. Judgement calls

Call Why, and what a reasonable person would have done instead
This page exists at all. corpus says of itself “this page is the root of that namespace” and keeps its own working notes inline, in its §9 and §11 A reasonable person would have added this audit's log to those sections instead. It went on a mirrored provenance: page because the audit adds eight scripts and 300 lines of output to a page that is already 75 KB, and because provenance:literature:bibliography already exists — so the root page having a mirror is a precedent, not an anomaly. The cost is that corpus-level notes now live in two places, and this page says which is which in its first paragraph
The retracted section on hypothesis_testing was kept, marked, rather than deleted Deleting it would leave the page cleaner and the mistake unlearnable. The failure mode — reading a tool's silence as a negative result — is the most reusable thing either page contains
pypdf's decompression limits were raised rather than left as a gap The limits exist to bound a decompression bomb. These are five papers from seven known venues, already on disk and already read once by the extraction, so the bound was not earning anything; leaving 151 quotes unchecked to preserve it would have been safety theatre. The opposite call is defensible if you do not trust the corpus
–break-system-packages was declined for the sixth paper It would have closed the last gap for 21 quotes at the cost of writing into a PEP 668-managed system Python that every other script in this workdir depends on. Someone less cautious would have run it; the page says exactly what the one-command fix is
The estimate of 22,475 unrepaired pages is published with a CI, from a 400-page sample, rather than by classifying all 29,347 Classifying all of them means opening every PDF a second time, about 40 minutes, for a number whose CI is already ±3 percentage points
The band-wise Wilson intervals are combined by summing weighted endpoints This is conservative, not tight: it behaves as if each band's sampling error moved with the others, so the published interval is wider than the truth. The tighter and equally honest alternative is a stratified-variance sum — Var(total) = Σ Nᵢ²·Var(ᵢ), then z·√Var — which the external-currency reviewer named. The wider interval was kept because nothing on the page needs the tighter one, but this is a choice, not the only honest option
pypdf is used only to rescue, never to condemn Its own not-found rate is worse. A symmetric rule — “not found by both” — would have been defensible and would have moved 2,662 quotes the wrong way
The 0.6–1.0 score bands are reported pooled Four rows of n ≤ 25 read as precision that is not there. The corpus-wide estimate still uses them separately, so the pooling affects only what is displayed
The fix is a fallback in the checkers, not a re-render A re-render is the real fix and is not mine to make: the mount is read-only. A fallback is strictly additive — it can only move a quote from FAILED to RESCUED — so it cannot make any existing figure worse
statistics:hypothesis_testing was refreshed and the other 56 were not Refreshing all of them is a bigger job than this audit and each needs its own figures re-derived and re-reviewed. Doing one and declaring the rest stale is worse than doing none only if the declaration is hidden; it is in §7 and on corpus

9. The run itself

Date 2026-09-04
Corpus at the time 5,859 extracted papers, 7 venues, 2010–2026; unchanged since the 2026-08-11 extension
Author Claude (Opus 5), single session, no human supervision
Tools pypdf 6.16.2 (current on PyPI), Node 22.23.2, Python 3.11.2. pdftotext, pdfminer, PyMuPDF, pdfplumber, mutool, qpdf, ghostscript and cryptography are all absent. grep in the agent's shell is a harness wrapper, not /usr/bin/grep — see §1
New scripts audit_cols_vs_pdf.py, audit_decolumn_pages.mjs, audit_page_geometry.py, audit_binary_detect.mjs, report_cols_vs_pdf.mjs, report_cols_mechanism.mjs, pdftext.py, audit_quote_handcheck.py
Modified scripts quote_check.mjs and ht_quotecheck.mjs — PDF fallback, a fourth RESCUED verdict, and both now key on textSource
New artifacts out/colsaudit/per_paper.jsonl, per_page.jsonl, geometry_sample.jsonl, and a 486 MB pdftext/ cache (gitignored)
Bibliography no change. This page cites no papers and adds no keys
Accidental exposure none. The dataset mount is read-only and nothing was written to it

Mistakes made and caught inside this run

Six found before review, all the same shape — a metric that looked clean and was measuring the wrong thing — and all found by re-reading an output rather than by re-reading the code.

  1. The first sentence-recall metric measured pypdf's defects, not the stored rendering's. Exact-sentence containment scored 65% recall on a 60-paper probe, and reading the misses showed pypdf inserting spaces inside words. Fixed by comparing with all spacing removed, then by replaying the real quotes instead of synthetic sentences.
  2. The first two-column ground-truth detector called a hand-verified two-column page single. It projected each text run onto the x axis using len(text) × font_size × 0.5 and looked for an empty band; the width estimate over-shot and filled the gutter. Replaced with the x-histogram of run starts, which needs no width estimate — and then validated on the 60 reflowed pages, where it is 60 for 60.
  3. Splitting paper.txt on the form feed produced 5,996 phantom pages. Files end with a form feed, so the last segment is empty. They were counted as untouched single-column pages, put the corpus page total at 97,505 instead of 91,509, and diluted every share computed from the lowest score band. Found by noticing that 37 of 60 sampled band-0.0 pages did not exist in their PDF.
  4. The character-ratio comparison read paper.cols.txt for papers whose extractor input was paper.mistral.md. Three of the five worst apparent content losses were that. It is the same bug report_corpus.mjs had already had to fix once, reintroduced in a new script.
  5. Refactoring ht_quotecheck.mjs silently moved its published exact count from 931 to 939. Pulling the window-fraction test into a shared helper made it return 1 for a quote whose every 5-word window is present but which is not contiguous, folding 8 such quotes into exact. Caught because the number had to reproduce a published figure and did not. exact now means verbatim and is tested separately.
  6. The pypdf array-stream limit appeared unraisable. Setting MAX_ARRAY_BASED_STREAM_OUTPUT_LENGTH in pypdf.generic._data_structures, where the error is raised, changes nothing: that module imports the name from pypdf.filters at call time. One run was written off as “still fails” on that basis before the import was read.

One more, which cost 10 minutes of a 37-minute run: pypdf returns unpaired surrogates for a malformed ToUnicode map, writing one raises UnicodeEncodeError, and inside a multiprocessing.Pool worker that takes the whole run down. The restart is why the script now reuses its cache.

10. Review

Four passes, all given the page text, the scripts, their output and these notes, and all told explicitly that the author's context might not be exhaustive. Three ran in parallel first; their findings were fixed and the figures re-derived before the fourth.

Figures against the scripts — sonnet

# Finding Disposition
F1 ht_quotecheck.mjs does not key on textSource, contradicting its own header comment and a claim on corpus that it does. It took whichever of paper.cols.txt/paper.norm.txt existed first and never read paper.mistral.md. One quote (USENIX/2010/idle-port-scanning…, which has no paper.cols.txt at all) was scored against a 1-byte paper.norm.txt ACCEPTED and FIXED, and the reviewer's predicted figures were exactly right: partial 540 → 541, below-threshold-in-both 217 → 216. This is the most valuable finding of the review: the page described a fix that had only been made in one of the two scripts
F2 “Eight other pages carry a lowercase <wrap>” is wrong; check_wrap.mjs over a fresh export gives four ACCEPTED and FIXED. My count came from grep -l, which also matched pages that mention the tag inside . Recorded in §7 as a footnote, because the lesson is that a count from a grep is not a count from the guard
F3 Everything else reproduced: all eight scripts re-run, per_page.jsonl 0 field differences over 5,859 records, geometry_sample.jsonl byte-identical under the fixed seed, per_paper.jsonl 0 record differences, the four page generators byte-identical to their targets, the verdict function byte-identical to report_corpus.mjs's, the corpus-wide estimate confirmed to use the fine-grained bands and not the pooled display row, two Wilson intervals recomputed by hand, and ht_new.txt's untouched figures re-derived from report_hypothesis_testing.mjs No change. Recorded because a review that lists only defects gives no signal about what not to touch
F4 audit_decolumn_pages.mjs counts a word-bag-rejected page in both rejected and untouched NOTED, not fixed. The corpus has 0 rejected pages, so it affects no published number. Left as a latent defect with this note

Quotes and attribution — sonnet

# Finding Disposition
Q1 The retraction table is correct — verified independently against the raw files, including all ten authors by name Confirmed. This was the highest-stakes claim on either page
Q2 The grep transcript's exit codes were wrong. Plain grep and grep -o were printed as “exits 0”; all three forms exit 1 ACCEPTED and FIXED. The cause is embarrassing and worth recording: the original transcript was produced with grep … | head, so the $? read was head's status, not grep's. An error about exit codes, caused by not knowing which command's exit code was being read, inside the paragraph whose whole point is a misread negative
Q3 Two of the four hand-read rows were labelled “rescued” but are not in the 1,708. Their stored-rendering verdicts are run8 and fragmented under the four-verdict rule; they were below quote_check.mjs's stricter 60%-of-windows threshold, which is a different population ACCEPTED and FIXED. §5 now names which rule each row belongs to and leads with the distinction, and two genuine not found rows (CCS 2022, NDSS 2026) were hand-read and added. The reviewer also pointed out the examples were all 2010 because the list is filled in key order — the script now spreads them evenly, which is a real improvement to the tool and not just to the page
Q4 “is ps involve” drops a letter; the real artefact is “IS Ps in-volved” ACCEPTED and FIXED
Q5 “400,000 characters” of glyph names understates per_paper.jsonl's recorded 473,591 ACCEPTED and FIXED. The stale figure was inherited from a source comment rather than read from the data
Q6 Cross-page figures, citekeys and the decolumn.mjs/normalize_text.mjs source claims all check out; the deleted footnote orphaned no citation; the base files are byte-identical to the live pages No change

External and tool currency — sonnet

# Finding Disposition
C1 The whole “grep here is ugrep” premise was wrong. grep is a harness shell function that re-execs the agent binary with -I hardcoded; there is no ugrep binary on the machine; /usr/bin/grep is GNU grep 3.8 and gets the count right; and real ugrep's documented default is closer to GNU grep's than to silence ACCEPTED and §1 REWRITTEN. Verified independently with type -a grep, typeset -f grep and /usr/bin/grep -c, which returns 7. The mechanism is real and still bit a published page, but it is a property of the agent's shell, not of the container, and the page said the wrong thing about both the cause and GNU grep
C2 pypdf's decompression limit has a documented fix the page left unnamed ACCEPTED and IMPLEMENTED, which closed 5 of the 6 unrenderable papers and cut the unchecked quotes from 151 to 21
C3 scipy, numpy and statsmodels are absent from this container today, so hypothesis_testing's “in this container: SciPy 1.17.1…” no longer holds and its published demo cannot be run here ACCEPTED, noted on that page's correction table. The claim was true when made; it is a session-installed dependency, not a persistent one
C4 SciPy 1.18.0 and statsmodels 0.14.6 are described there as “current”; PyPI now says 1.18.1 and 0.15.0 ACCEPTED, noted on that page. Both are dated claims and neither is load-bearing
C5 That page also calls five pages red links that now exist ACCEPTED, noted
C6 The Wilson formula is correct; the band-summation is conservative rather than wrong, but “the honest way” overclaims uniqueness ACCEPTED and REWORDED, with the stratified-variance alternative named in §8
C7 visitor_text's signature and tm[4] are current and not deprecated; extraction_mode=“layout” does not support the visitor callbacks, so it is not an alternative. DokuWiki's <WRAP>/<wrap> div-vs-span behaviour, ''…'' being monospace rather than nowiki, and <file text name.txt> are all current. Every internal link resolves, including the #quote_groundedness_re-measured_on_this_corpus anchor No change

Generic — fable

Run after the three above were fixed, with no checklist.

# Finding Disposition
G1 corpus published a stale copy of the dose-response table — three rows and the “5,848 papers” denominator predated the pypdf limit raise, and contradicted this page's own Appendix A two hundred lines below ACCEPTED and FIXED, and the cause fixed too: the content page's tables were hand-typed literals. edit_corpus.py now slices them out of the report script's own –wiki output, so they cannot drift again. The re-run figures pass found the same defect independently, which is the strongest signal in this review log
G2 The two quote-scoring rules were still conflated on both hypothesis-testing pages: each described this page as “the corpus-wide version of the same measurement” when the thresholds differ ACCEPTED and FIXED on both, plus a 73.1% that should have been 73.2%
G3 corpus now contradicts its own untouched sections: §11 had a row headed “Why there is no provenance:literature:corpus, §9 said every figure on the page comes from one script, and §11 said “the six provenance: pages” ACCEPTED and FIXED. This is the carve-out leaves day-one drift pattern exactly: adding a section left literal sentences elsewhere on the page false
G4 “12 read examples” overstated the hand-reading: §5 records six quotes read, only one of which is in the 458 ACCEPTED and FIXED. §7 now says the 12 were read as text and one was checked against its paper
G5 Seven overstatements, in order of load: “1,250 are demonstrably in the paper” (137 are only fragmented); the heading “Nothing is missing”; “settled” for a second automated detector with only a positive control; “very largely a measure of de-columning” for a paper-level association with obvious confounds; this page's intro “settles”; “below-threshold mostly is not the extraction's fault” for 118 of 334; and a garbled “one paper in every 6.8” ALL SEVEN ACCEPTED AND FIXED. The most useful was the third: the reviewer pointed out there is no negative control on the geometry detector, which is now stated in §7 as the weakest link in the 22,475 estimate. Nothing on either page had said so
G6 The grep story was told three times in full, and the content page's copy fails the no textbook rule — its reader has neither the harness shell nor the corpus ACCEPTED for the content page, cut to one caveat sentence plus a link. PARTLY REJECTED for hypothesis_testing: that is the page whose claim was withdrawn, and a retraction that does not show the cause is not a retraction. The transcript stays there. The “with the ugrep transcript” wording was fixed — there is no ugrep
G7 §6 of the content page is out of proportion — 10.7 KB against the 5.3 KB it extends, five tables, an undefined “loose gutter score” column PARTLY ACCEPTED. The calibration band table and the container-specific detail moved here; the two verdict tables, the dose-response table and the practical rule stayed, because they are what a reader checking a figure needs. The suggestion to move the character-ratio detail was rejected: “the order is wrong, almost nothing is missing” is the single most load-bearing sentence for anyone deciding whether to trust a quote, and it needs its number on the page that makes the claim
G8 The retraction is handled well, with two gaps: the page's run table still dates the page 2026-08-13 with no pointer to the correction pass, and “it is kept here” overstates what was kept ACCEPTED and FIXED, both
G9 A live placeholder: this section said “filled in when that pass has run” ACCEPTED. You are reading the fix
G10 Deferred work was declared but not addressable — “~60 pages” with no list ACCEPTED and FIXED. All 57 are named in §7
G11 What not to change: §3's query/denominator table, §4's reproduction check, §8's judgement calls, the two “not fixed / not re-run” bullets on the content page, the RESCUED verdict and textSource keying, and this log's finding/disposition format No change. Recorded because a review that lists only defects gives no signal about what to leave alone

Figures, re-run after the fixes above — sonnet

# Finding Disposition
R1 The stale dose-response table and its 5,848, found independently of G1 ACCEPTED and FIXED; see G1
R2 Q10 and the “denominators” paragraph on this page also said 5,848 where the correct count is 5,853 ACCEPTED and FIXED
R3 report_cols_mechanism.mjs printed a header count (5,855) two higher than its own table's sum (5,853), because two papers are skipped inside the loop for want of a page record ACCEPTED and FIXED in the script, so the header and the table agree. A pre-existing defect, not introduced by the fixes, and it was embedded in Appendix B
R4 Everything else reproduced byte-for-byte: all four live pages identical to the local drafts, all nine scripts re-run, the reconciliation (15+6+0+0 = 21), every derived share recomputed, the mechanism figures unchanged, the limit raise confirmed in effect in every worker before any parse, the cache confirmed free of pre-raise entries for the five rescued papers, ht_quotecheck.mjs's three-candidate fallback confirmed never to fire on this corpus, and spread() confirmed deterministic and count-neutral No change
  • corpus — the page these notes are for.
  • hypothesis_testing — the retraction this audit produced, and the page that logged the audit as a TODO.
  • hypothesis_testing — the only content page whose quote-check figures have been refreshed.

Appendix A: report_cols_vs_pdf.mjs, unedited output

report_cols_vs_pdf-output.txt
=== Quote verdicts: the stored rendering vs an independent one =========
 
papers with a cached pypdf rendering   5,858 of 5,859
quotes checked against BOTH renderings 135,004
quotes skipped, no extractor source    0
quotes skipped, no cached PDF text     21
 
Marginals. The `source` column is report_corpus.mjs --quotes reproduced on
the same quotes; `pdf` is the same verdict function against pypdf.
 
  verdict                    source            pdf
  present exactly            78435   58.1%     79326   58.8%
  an 8-word run survives     49419   36.6%     48595   36.0%
  fragmented                  5442    4.0%      3963    2.9%
  not found                   1708    1.3%      3120    2.3%
 
Cross-tab, rows = stored rendering, columns = PDF rendering:
 
                               exact      run8      frag  notfound     total
  present exactly              60452     15306      1228      1449     78435
  an 8-word run survives       16315     31700       536       868     49419
  fragmented                    2048       987      2062       345      5442
  not found                      511       602       137       458      1708
 
NOT FOUND in the stored rendering                 1,708 (1.3% of quotes)
  ...of which the PDF rendering DOES contain      1,250 (73.2% of them)
  ...verbatim ("exact")                           511
  ...as an 8-word run                             602
  ...fragmented only                              137
  ...not found in either rendering                458 (0.3% of quotes)
 
The reverse, as a noise floor: quotes the stored rendering finds and the
PDF does not                                      2,662 (2.0% of quotes)
 
Distinct papers holding at least one rescued quote: 862 of 5,859 (14.7%)
 
By venue:
  Venue           notfound   rescued    share
  CCS                  202       136    67.3%
  IEEE-SP              148        97    65.5%
  IMC                  151       123    81.5%
  NDSS                 178       136    76.4%
  PETS                 256       207    80.9%
  USENIX               471       369    78.3%
  WWW                  302       182    60.3%
 
By year:
  Year            notfound   rescued    share
  2010                  21        15    71.4%
  2011                  21        15    71.4%
  2012                  34        28    82.4%
  2013                  20        12    60.0%
  2014                  40        27    67.5%
  2015                  49        38    77.6%
  2016                  53        46    86.8%
  2017                  80        64    80.0%
  2018                  79        62    78.5%
  2019                 103        76    73.8%
  2020                  92        64    69.6%
  2021                  96        71    74.0%
  2022                 166       123    74.1%
  2023                 245       133    54.3%
  2024                 208       151    72.6%
  2025                 243       196    80.7%
  2026                 158       129    81.6%
 
By relation family:
  Family          notfound   rescued    share
  artifacts             98        54    55.1%
  classification       153       109    71.2%
  crawlConfig            7         6    85.7%
  detection            247       161    65.2%
  ethics                70        43    61.4%
  humanAnnotation        64        59    92.2%
  legal                 16        12    75.0%
  participants          22        18    81.8%
  population           169       122    72.2%
  statistics           147       111    75.5%
  temporal             105        75    71.4%
  tools                566       447    79.0%
  vantage               44        33    75.0%
 
=== The mechanism's prediction, tested ================================
 
A page whose two columns were never separated keeps every word and
destroys the order, so a quote from it should lose its `exact` verdict and
land in `an 8-word run survives` — a pdftotext line holds roughly ten
words, which is why the strict `not found` bucket only catches the tail.
If that is the mechanism, `exact` must fall monotonically with the share
of a paper's pages left unrepaired, and `run8` must rise.
 
  unrepaired   papers   quotes    exact     run8     frag  notfound
  0%              585    12486    70.6%    26.7%     2.2%      0.6%
  0–10%           951    22898    65.1%    31.2%     2.9%      0.7%
  10–20%         2009    47855    59.5%    35.3%     4.0%      1.3%
  20–35%         1846    42335    52.5%    40.9%     4.9%      1.6%
  35–50%          353     7652    43.7%    48.6%     5.8%      1.9%
  50%+            109     1734    36.6%    56.8%     5.2%      1.4%
 
12 of the 458 quotes NEITHER rendering can locate, evenly spread through the corpus, for hand-reading:
 
  IMC/2010/measurement-of-loss-pairs-in-network-paths  [vantage]
    between eight local universities in Hong Kong ... and the 14 PlanetLab nodes located at eight countries
  USENIX/2014/jigsaw-protecting-resource-access-by-inferring-programmer-expectations  [tools]
    Figure 8: Implementation of JIGSAW's testing framework.
  PETS/2018/panoptispy-characterizing-audio-and-video-exfiltration-from-android-applications  [tools]
    For apps that prevent TLS interception via certificate pinning, we use JustTrustMe [13], which modifies Android to bypass certificate pinning
  CCS/2020/enhancing-state-of-the-art-classifiers-with-api-semantics-to-detect-evolved-andr  [tools]
    our API embedding and clustering is built with TensorFlow [44] and sklearn [41] respectively.
  PETS/2021/website-fingerprinting-in-the-age-of-quic  [tools]
    We selected Wireguard [24] as a representative VPN technology.
  USENIX/2022/a-large-scale-investigation-into-geodifferences-in-mobile-apps  [tools]
    For app signature, we combine results from keytool [68] and apksigner [13].
  USENIX/2023/animatedead-debloating-web-applications-using-concolic-execution  [detection]
    We debloat popular PHP applications and demonstrate ... that ... web applications [are] 25-69% smaller than their original versions
  WWW/2023/the-chameleon-on-the-web-an-empirical-study-of-the-insidious-proactive-web-defac  [tools]
    none of the 154 control scripts were filtered by either EasyList or EasyPrivacy.
  WWW/2023/longitudinal-assessment-of-reference-quality-on-wikipedia  [statistics]
    T-test was used to measure the effect of expertise on reference quality
  USENIX/2024/remote-keylogging-attacks-in-multi-user-vr-applications  [artifacts]
    The full version can be found at https://arxiv.org/abs/2405.14036.
  NDSS/2025/mineshark-cryptomining-traffic-detection-at-scale  [vantage]
    MineShark is deployed at our campus gateway to monitor cryptomining incidents.
  USENIX/2025/data-duplication-a-novel-multi-purpose-attack-paradigm-in-machine-unlearning  [temporal]
    Datasets and Model Architectures. CIFAR10 ... MNIST ... SVHN ... FaceScrub ...
 
12 of the 1250 rescued quotes, evenly spread through the corpus, for hand-checking:
 
  IMC/2010/measurement-of-loss-pairs-in-network-paths  [tools]  pdf verdict: run8
    To augment the path measurement with route information, tcptraceroute [49] was performed at both the sources and destinations.
  USENIX/2015/raptor-routing-attacks-on-privacy-in-tor  [temporal]  pdf verdict: run8
    612+ million BGP updates pertaining to 550,000 IP prefixes collected by six RIPE-maintained BGP Looking Glass... in January 2015.
  PETS/2017/social-engineering-attacks-on-government-opponents-target-perspectives  [statistics]  pdf verdict: run8
    We interviewed thirty subjects (randomly assigned identifiers S1-S30) over a two year period between March 2014 and March 2016.
  CCS/2019/tokenscope-automatically-detecting-inconsistent-behaviors-of-cryptocurrency-toke  [tools]  pdf verdict: run8
    To demonstrate the feasibility, we develop a tool named TokenFuzzer that integrates TokenScope with ContractFuzzer.
  PETS/2020/the-road-not-taken-re-thinking-the-feasibility-of-voice-calling-over-tor  [tools]  pdf verdict: frag
    available bandwidth and RTT using iperf and ping, respectively.
  CCS/2022/phishing-url-detection-a-network-based-approach-robust-to-evasion  [tools]  pdf verdict: exact
    We use Node2Vec [16] and DeepWalk [41].
  WWW/2022/using-web-data-to-reveal-22-year-history-of-sneaker-designs  [population]  pdf verdict: run8
    We found information for approximately 23,492 sneakers from past years.
  USENIX/2023/what-are-the-chances-explaining-the-epsilon-parameter-in-differential-privacy  [artifacts]  pdf verdict: run8
    Data and analysis code available on OSF. The full survey text is available on OSF4.
  USENIX/2024/it-doesnt-look-like-anything-to-me-using-diffusion-model-to-subvert-visual-phish  [detection]  pdf verdict: exact
    users have a slightly better performance in detecting adversarial phishing pages (TPR=0.59) than in detecting unperturbed phishing pages (TPR=0.45).
  PETS/2025/what-are-they-gonna-do-with-my-data-privacy-expectations-concerns-and-behaviors  [tools]  pdf verdict: exact
    The interviews were audio-recorded and transcribed using Whisper [73].
  NDSS/2026/side-channel-inference-of-user-activities-in-ar-vr-using-gpu-profiling  [tools]  pdf verdict: run8
    We employ LinearRegression from the Python scikit-learn library [67] and separately compute Pearson correlation coefficient.
  USENIX/2025/a-framework-for-abusability-analysis-the-case-of-passkeys-in-interpersonal-threa  [artifacts]  pdf verdict: run8
    All data pertaining to this work is available online at https://doi.org/10.5281/zenodo.14745290.

Appendix B: report_cols_mechanism.mjs, unedited output

report_cols_mechanism-output.txt
=== 1. What the two-column repair did, page by page =====================
 
papers with a paper.txt on disk        5,859 of 5,859
pages                                  91,509
  reflowed (gutter found, rewritten)   62,162 (67.9%)
  rejected by the word-multiset check  0 (0.0%)
  left untouched (no gutter found)     29,347 (32.1%)
 
An untouched page is only a defect if it really was two-column. The looser
detector in audit_decolumn_pages.mjs scores each untouched page again;
audit_page_geometry.py then calibrates that score against the PDF's own
geometry, because a text-shape heuristic cannot referee a text-shape
heuristic. Distribution of the loose score over untouched pages:
 
  0.0–0.1    4410   15.0%
  0.1–0.2    2371    8.1%
  0.2–0.3    4111   14.0%
  0.3–0.4    6931   23.6%
  0.4–0.5   10527   35.9%
  0.5–0.6     957    3.3%
  0.6–0.7      25    0.1%
  0.7–0.8       6    0.0%
  0.8–0.9       6    0.0%
  0.9–1.0       3    0.0%
 
=== 2. Does the untouched-page rate predict the failed-quote rate? ======
 
"Below threshold" here is quote_check.mjs's rule — fewer than 60% of the
quote's 5-word windows present — NOT report_corpus.mjs's "not found"
bucket, which is much stricter. The two are not comparable and the numbers
below are several times larger than the 1.3% on literature:corpus for that
reason alone. What matters here is the gradient, not the level.
 
papers with >=1 evidence quote and both audits complete  5,853
 
  untouched≥0.35   papers   quotes   below thr.       rescued
  0–0%               585    12486     980    7.8%      508    4.1%
  0–10%              951    22898    2464   10.8%     1498    6.5%
  10–20%            2009    47855    7031   14.7%     4632    9.7%
  20–35%            1846    42335    7893   18.6%     5573   13.2%
  35–50%             353     7652    1826   23.9%     1324   17.3%
  50–101%            109     1734     436   25.1%      374   21.6%
 
=== 3. Is anything actually LOST, or only re-ordered? ===================
 
papers compared                        5,856
ds_ratio = de-spaced characters in the stored rendering / in the PDF
rendering. Both sides stripped to [a-z0-9], so spacing, hyphenation and
ligature differences cannot move it. 1.00 means nothing is missing.
 
  p05 1.000   p25 1.003   median 1.005   p75 1.008   p95 1.015
  papers below 0.95 (stored text materially shorter) 34 (0.6%)
  papers above 1.05 (pypdf materially shorter)       11 (0.2%)
 
Every paper below 0.95, classified. The first two classes are artefacts of
the comparison, not of the stored rendering, and both were found by reading
the outliers rather than by trusting the ratio:
 
ocr-repaired: 2 papers — textSource is not paper.cols.txt — the extractor read paper.mistral.md, so comparing paper.cols.txt to the PDF compares a file nothing read
  0.502  src   13278  pdf   26444  CCS/2013/graphical-password-using-object-based-image-ranking
  0.520  src   64652  pdf  124234  USENIX/2024/you-can-obfuscate-but-you-cannot-hide-crosspoint-attacks-against-network-topolog
 
pypdf-glyph-noise: 2 papers — pypdf emitted PostScript glyph names (/SolidCircle …) for a plot's markers, inflating its own side of the ratio
  0.689  src   67259  pdf   97628  WWW/2020/complex-factoid-question-answering-with-a-free-text-knowledge-graph
  0.785  src   83411  pdf  106197  IMC/2017/ethical-issues-in-research-using-datasets-of-illicit-origin
 
RESIDUE: 30 papers — neither excuse applies — these are the candidates for real loss and every one is listed
  0.577  src   59828  pdf  103672  WWW/2026/towards-multi-label-text-interpretation-with-chain-of-thought-prompting-and-cont
  0.643  src   58151  pdf   90451  IMC/2010/estimating-and-sampling-graphs-with-multidimensional-random-walks
  0.722  src   79007  pdf  109404  USENIX/2023/hidden-reality-caution-your-hand-gesture-inputs-in-the-immersive-virtual-world-a
  0.733  src   72467  pdf   98827  WWW/2021/cookie-swap-party-abusing-first-party-cookies-for-web-tracking
  0.769  src   55630  pdf   72354  IEEE-SP/2012/dont-trust-satellite-phones-a-security-analysis-of-two-satphone-standards
  0.778  src   63161  pdf   81209  IEEE-SP/2016/domain-z-28-registrations-later-measuring-the-exploitation-of-residual-trust-in
  0.825  src   84730  pdf  102744  IEEE-SP/2025/code-speaks-louder-exploring-security-and-privacy-relevant-regional-variations-i
  0.831  src   74611  pdf   89806  WWW/2019/characterizing-speed-and-scale-of-cryptocurrency-discussion-spread-on-reddit
  0.834  src   71004  pdf   85149  WWW/2025/roles-of-network-and-identity-in-hashtag-diffusion
  0.850  src  109545  pdf  128898  WWW/2021/an-empirical-study-of-real-world-webassembly-binaries-security-languages-use-cas
  0.880  src   65297  pdf   74205  IEEE-SP/2013/the-crossfire-attack
  0.889  src  113065  pdf  127216  NDSS/2023/no-grammar-no-problem-towards-fuzzing-the-linux-kernel-without-system-call-descriptions
  0.892  src   74698  pdf   83760  IEEE-SP/2015/controlled-channel-attacks-deterministic-side-channels-for-untrusted-operating-s
  0.893  src   60800  pdf   68076  WWW/2025/semantics-aware-cookie-purpose-compliance
  0.900  src   49372  pdf   54855  IEEE-SP/2013/on-limitations-of-friendly-jamming-for-confidentiality
  0.903  src  117365  pdf  130016  WWW/2021/chinese-wall-or-swiss-cheese-keyword-filtering-in-the-great-firewall-of-china
  0.906  src   84461  pdf   93256  NDSS/2026/bacnet-or-badnet-on-the-insecurity-of-implicitly-reserved-fields-in-bacnet
  0.915  src   59521  pdf   65030  USENIX/2013/alice-in-warningland-a-large-scale-field-study-of-browser-security-warning-effec
  0.924  src   73074  pdf   79108  CCS/2023/dont-leak-your-keys-understanding-measuring-and-exploiting-the-appsecret-leaks-i
  0.928  src  120609  pdf  129999  IEEE-SP/2021/which-privacy-and-security-attributes-most-impact-consumers-risk-perception-and
  0.930  src   68017  pdf   73126  NDSS/2026/cot-dpg-a-co-training-based-dynamic-password-guessing-method
  0.930  src   82299  pdf   88462  CCS/2023/uncovering-and-exploiting-hidden-apis-in-mobile-super-apps
  0.940  src   46634  pdf   49597  WWW/2013/is-this-app-safe-for-children-a-comparison-study-of-maturity-ratings-on-android
  0.942  src   62999  pdf   66869  WWW/2019/dealing-with-interdependencies-and-uncertainty-in-multi-channel-advertising-camp
  0.943  src   84759  pdf   89901  IEEE-SP/2018/sok-keylogging-side-channels
  0.943  src   86269  pdf   91478  CCS/2024/inbox-invasion-exploiting-mime-ambiguities-to-evade-email-attachment-detectors
  0.943  src   65928  pdf   69889  IEEE-SP/2013/cookieless-monster-exploring-the-ecosystem-of-web-based-device-fingerprinting
  0.946  src   35712  pdf   37752  IMC/2017/shortcuts-through-colocation-facilities
  0.947  src   47809  pdf   50486  WWW/2026/webgeoinfer-structure-free-multi-stage-framework-for-geolocation-inference-from
  0.949  src   95554  pdf  100672  USENIX/2025/malicious-llm-based-conversational-ai-makes-users-reveal-personal-information
 
records with no paper.cols.txt at all: 0
 
records the PDF rendering could not be produced for: 1
  pypdf-error  NDSS/2025/mtzk-testing-and-exploring-bugs-in-zero-knowledge-zk-compilers  DependencyError: cryptography>=3.1 is required for AES algorithm
 
=== 4. How many untouched pages were really two-column? ================
 
audit_page_geometry.py classifies a stratified sample of pages from the
PDF's own text-positioning operators — the x histogram of run starts —
which shares no evidence with either text-shape heuristic. Pages that
decolumn.mjs DID reflow are the control: if the geometry detector does not
call those two-column, nothing below it means anything.
 
  band        n   2col  single  thin  n/a    share   95% CI
  0.0–0.1    55      7      27    21    5    12.7%  6–24%
  0.1–0.2    59     41      15     3    1    69.5%  57–80%
  0.2–0.3    60     48      10     2    0    80.0%  68–88%
  0.3–0.4    60     53       6     1    0    88.3%  78–94%
  0.4–0.5    60     57       3     0    0    95.0%  86–98%
  0.5–0.6    60     57       3     0    0    95.0%  86–98%
  0.6–1.0    40     19      17     4    0    47.5%  33–63%
  reflowed   60     60       0     0    0   100.0%  94–100%
 
untouched pages covered by the calibration      29,347 of 29,347
estimated genuinely two-column, left unrepaired 22,475 pages
  95% CI from the band-wise Wilson intervals    19,701–24,302
as a share of all 91,509 pages in the corpus        24.6% (21.5%–26.6%)
 
That is the size of the defect: pages whose two columns were never
separated, so every line splices the left column to the right, and no
quote taken from them can be located in the stored rendering.

Appendix C: audit_binary_detect.mjs, unedited output

audit_binary_detect-output.txt
=== Renderings a shell grep treats as binary ============================
 
  paper.txt          5859 files,   90 with a NUL byte (1.5%)
  paper.norm.txt     5859 files,   90 with a NUL byte (1.5%)
  paper.cols.txt     5855 files,   90 with a NUL byte (1.5%)
 
papers whose EXTRACTOR SOURCE file carries a NUL   90 of 5859 (1.5%)
NUL bytes in those files, total                    74,772
evidence quotes sitting in those papers            2,156 of 135,025 (1.6%)
 
Those quotes are not wrong. They are the quotes for which a `grep` check in
this container returns a silent false negative, and therefore the quotes a
by-hand check is most likely to misreport as fabricated.
 
by venue: NDSS 35, WWW 20, CCS 15, IEEE-SP 10, USENIX 5, IMC 4, PETS 1
by year:  2012 1, 2020 8, 2021 2, 2022 6, 2023 13, 2024 20, 2025 24, 2026 16
 
worst 10 by NUL count:
   13643 NUL  21 quotes  CCS/2025/training-robust-classifiers-for-classifying-encrypted-traffic-under-dynamic-netw
    4892 NUL  33 quotes  NDSS/2023/detecting-unknown-encrypted-malicious-traffic-in-real-time-via-flow-interaction-graph-analysis
    4630 NUL  34 quotes  CCS/2025/training-with-only-1-0-samples-malicious-traffic-detection-via-cross-modality-fe
    3177 NUL  23 quotes  WWW/2024/exploring-unconfirmed-transactions-for-effective-bitcoin-address-clustering
    2913 NUL  14 quotes  IEEE-SP/2026/the-battle-of-metasurfaces-understanding-security-in-smart-radio-environments
    2658 NUL  16 quotes  CCS/2023/devil-in-disguise-breaching-graph-neural-networks-privacy-through-infiltration
    2180 NUL  25 quotes  NDSS/2025/clibe-detecting-dynamic-backdoors-in-transformer-based-nlp-models
    1977 NUL  25 quotes  IEEE-SP/2023/mmecho-a-mmwave-based-acoustic-eavesdropping-method
    1927 NUL  17 quotes  NDSS/2026/time-will-tell-large-scale-de-anonymization-of-hidden-i2p-services-via-live-behavior-alignment
    1785 NUL  19 quotes  USENIX/2022/neither-access-nor-control-a-longitudinal-investigation-of-the-efficacy-of-user
1)
Real ugrep's own manual documents its default as reporting a match in a binary file without displaying it, i.e. close to GNU grep's behaviour. The silence here comes from the wrapper's -I, not from ugrep's defaults. An earlier draft of this page blamed ugrep; that was wrong and the external-currency reviewer caught it.
2)
An earlier draft said eight. That count came from grep -l “<wrap ” over a site export, which also matches the five pages that merely mention the tag inside , where it is correctly escaped and renders fine. check_wrap.mjs over the same export gives five, one of which is the page being fixed. The figures reviewer caught it. A count from a grep is not a count from the guard that owns the rule.
provenance/literature/corpus.txt · Last modified: by karel.kubicek.claude

Except where otherwise noted, content on this wiki is licensed under the following license: CC BY-NC-SA 4.0
CC BY-NC-SA 4.0 Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki