Release review of the download-log piece, its short form, the front page that carries it, and the record behind them
Findings
This is the release gate for a new piece, articles/what-a-download-shows.md, its illustration, its short form, and the front page that carries it (README.md above the horizontal rule), together with the study record studies/LH005/ and the four new entries S20 to S23 in sources.md. The reviewer read the dispatch, AGENTS.md and R-0004, then the piece once straight through as a newcomer would, then sentence by sentence against studies/LH005/LH005.md at version 0.1, its brief, its source assessment, and the 37 tables in studies/LH005/data/. Unlike R-0004, this review did fetch: the record's counts were re-queried from ClickPy with eleven small SQL queries (one of which the server refused for a syntax fault of the reviewer's own, and which a local recomputation replaced), pypistats.org's overall series was read again, and the eight documentation pages the record quotes were fetched and every quotation searched for in their text. Every derived figure the piece uses, and most the record uses, was also recomputed with a short Python script from the retained reads, so that the check runs both from the primary source to the record and from the record's own inputs to its outputs. The piece's SVG was regenerated from its script and compared byte for byte, and rendered in headless Chromium in light and dark mode and looked at.
The verdict is that the piece, the short form and the front page can be released after the must-fixes below, none of which changes a conclusion: every count reproduces from ClickPy to the digit, every quotation is on its page, and every link resolves. What must change is three figures in the record that its own tables do not support as worded (the reading times, the lean-lsp-mcp shares, and "smaller than the day-to-day swing"), one figure in the piece and the record that mislabels its denominator ("all older versions" for a class that leaves one older version out), two sentences in the standfirst and on the front page whose verb ("It shows") is firmer than the record's label (interpretation), and one adverb ("barely") that the per-week figures do not bear.
The piece, sentence by sentence, against the record and its tables
Line numbers are the piece's. "Live" means the reviewer's own ClickPy query on 26 September at 17:39 UTC; "recomputed" means from the retained reads in data/.
| Piece passage | Checked against | As the record has it? |
|---|---|---|
| Line 3: "On 3 April 2026 ... downloaded 3,201,463 times. That was 48 of every hundred downloads ... and on the day after, more than half" | Live: 3 April 3,201,463 of 6,657,180 (48.09 per cent); 4 April 2,673,423 of 5,243,831 (50.98) | Yes |
| Line 3: "none had yet been seen to take the new version up. The first to write a requirement for exactly that version did so on 8 April" | LH002 propagation_candidates.csv: R04 first seen 4 April 16:20 UTC; R03 ==1.27.0 at 8 April 18:26 |
Yes |
| Line 11: "Each entry names the library, the version, the day, the installer ... and whether the installer said it was running on a build server" | sources.md L2 and L8: the original keeps a timestamp; ClickPy keeps the date | True of the copy read, not of the log the sentence describes (finding 9) |
| Line 13: "three public copies"; "Only ClickHouse's copy reaches back to April with the version and installer"; "matched ClickHouse's exactly on 17 [of 25] and were never more than about one per cent apart" | Live pypistats series 29 March to 25 September, 181 days; recomputed: 25 window days, 17 identical, largest 1.004 per cent | Yes |
| Line 15: the packaging guide "calls download counts 'Highly inaccurate': installers' caches lower them, private mirrors can raise or lower them, and scripts can inflate them" | Fetched page: "Highly inaccurate: ... pip's download cache (lowers download counts) ... Internal or unofficial mirrors (can both raise or lower download counts) ... Unofficial scripts or attempts at download count inflation (raises download counts)"; "Last updated on Sep 22, 2026" | Yes |
| Line 19: "between 4 and 12 million times a day"; "about 220 million times in the four weeks" | Recomputed: 4,075,518 to 11,727,399; 219,899,536 (by-version table) | Yes |
| Line 21: "14:48 UTC on 2 April"; "nine hours left"; "1,639,539 times, 22 per cent"; "48 ... 51"; "between 45 and 71 per cent"; "about 96 million"; "existed for only three of them"; the January release "passing 60 per cent the day after" | data/pypi_release_files.csv 2026-04-02T14:48:07Z (9 h 12 min left); live 1,639,539 of 7,351,271 (22.3); recomputed 3 to 22 April 45.38 to 70.55; 95,672,297; 2 to 22 April is 21 days; 1.26.0 61.69 per cent on 25 January | Yes |
| Line 23: the five moves and their days; "about half of every day's downloads for five days" | LH002 table: 4, 8, 13, 14, 22 April; 3 to 7 April shares 48.1, 51.0, 48.6, 47.8, 45.4 | Yes ("about half" stretches to 45.4 on 7 April; the record says the same) |
| Line 25 alt text and line 27 caption | The figure's desc and the table; 3 April at 48.1 is before R04's 4 April | Yes |
| Line 31: "79 per cent ... uv and 20 per cent by pip"; "about four of every five downloads of the new version came through uv" | Live: 78.56, 20.4; 76,466,745 of 94,095,825 (81.26) | Yes |
| Line 33: "So a new environment set up on 3 April received 1.27.0 because it existed" ; "We think that is what most of these downloads were" | Record Answer: "(interpretation)" | "received" is a general claim, not an observation (finding 10); "we think" carries the rest |
| Line 35: "59 per cent of uv's ... 53 per cent of pip's, but 21 per cent of Poetry's and under 1 per cent of Bazel's" | Live: 58.85, 53.10, 21.23, 0.95 (234 of 24,660) | Yes |
| Line 35: "Poetry and Bazel are tools that usually install from a lockfile" | No source in the record; the record's own sentence is labelled interpretation; uv also has a lockfile | Unsourced background; the contrast with uv needs a clause (finding 11) |
| Line 35: "only 11 per cent of the new version's downloads carried it, against 49 per cent of the previous version's and 73 per cent of all older versions'" | Live: 1.27.0 10.58; 1.26.0 48.59; 1.25.0 59.61; "other" 72.90. All versions older than 1.26.0 together: 36,946,018 of 51,507,520, 71.7 per cent | No: 73 is the "other" class, which leaves 1.25.0 out (finding 4) |
| Line 35: "one that reports nothing is counted as not a build server" | Fetched L4: CAST(ifNull(ci, 0), 'Enum8(...)'); live: no "unknown" row in 3 to 22 April |
Yes |
| Line 39: "barely fell at weekends, to 0.88 of the weekday level, while the old version's fell to about half" | Live: 0.878, 0.517 over 6 to 26 April. Recomputed week by week: 1.27.0 1.24, 0.91, 0.62; without Sunday 12 April 0.82. 1.26.0 0.55, 0.48, 0.52 | The ratios yes; "barely" no (finding 7) |
| Line 41: "It keeps no field that identifies a client or a session" | data/clickpy_schema.csv: pypi ordered by (project, date, version, country_code, python_minor, system), columns as sources.md L8 lists |
Yes |
| Line 43: "22 minutes later"; "both require exactly 1.27.0"; "35,024 times"; "109,023,441"; "three in every ten thousand"; "fewer in three weeks than the new version's downloads usually rose or fell from one day to the next" | LH002: 18:26:34 to 18:49:02; live 35,024 and 109,023,441; 0.0321 per cent; recomputed day-to-day changes 8 to 29 April: 20 of 21 exceed 35,024, smallest 24,974, median 407,771 | Yes; "usually" is right (the record's own wording is not, finding 3) |
| Line 47: "on our reading not because the projects around it chose it, but because installers settling open ranges picked up whatever was newest"; "we think a bad one would travel as fast" | Record Answer "(interpretation)"; Next, second entry | Yes, with the hedge (finding 12) |
| Line 49: "one of the copies keeps only 180 days, so the four weeks we read will be gone from it after about 20 October" | 22 April plus 181 days is 20 October; live series begins 29 March, 181 days | Yes |
| Line 49: "it cannot tell a person from a build server or an agent" | Line 35 of the piece: the flag tells a build server when the installer reports one | Slightly stronger than its own line 35 (finding 13) |
| Colophon: the sources and dates; "between about 17:13 and 17:25 UTC"; "read the same day between about 12:55 and 13:40"; "version 0.1, 26 September 2026" | sources.md L1 to L9; data/read_log.csv 17:18:10 to 17:25:07 and page reads from 17:13:59; LH002 header; LH005 header version 0.1 | Yes (the record's own header disagrees with the colophon, finding 1) |
The record against the primary sources
Every count below was re-queried from ClickPy on 26 September 2026 between 17:39:44 and 17:39:48 UTC, five months after the events and twenty-one minutes after the study's own reads. No drift was seen: every figure came back identical to the record's, so the re-ingestion ClickHouse describes (L4) has not touched these days between 17:18 and 17:39.
| Figure | Record | Reviewer | Source of the reviewer's figure |
|---|---|---|---|
| 1.27.0 on 2, 3, 4 April: count, day total, share | 1,639,539 of 7,351,271 (22.3); 3,201,463 of 6,657,180 (48.1); 2,673,423 of 5,243,831 (51.0) | identical | live, by-version table |
| 1.27.0 over the window; window total (by-version table) | 95,672,297 of 219,899,536 | 95,672,297 of 219,899,536 | recomputed from data/clickpy_mcp_daily_by_version_window.csv |
| Window total, per-day table | 219,835,062 | 219,835,062 | live |
| Window total, installer table; per-download table | 219,940,356; 219,695,030 | identical | live |
| Daily range in the window | 4,075,518 to 11,727,399 | identical | recomputed |
| Share 3 to 22 April: range and median | 45.4 to 70.5, median 56.5 | 45.38 to 70.55, 56.49 | recomputed |
| uv, pip shares of the window | 78.6, 20.4 | 78.56, 20.40 | live |
| 1.27.0's share of uv, pip, Poetry, Bazel, 3 to 22 April | 58.9, 53.1, 21.2, 0.95 (234 of 24,660) | 58.85, 53.10, 21.23, 0.95 (234 of 24,660) | live |
| uv's share of 1.27.0, 3 to 22 April | (piece: four in five) | 81.26 | live |
| CI-flagged share of the window | 34.6 (75,971,844 of 219,695,030) | identical | live |
| CI-flagged share by class, 3 to 22 April | 1.27.0 10.6; 1.26.0 48.6; other 72.9 | 10.58; 48.59; 1.25.0 59.61; other 72.90; no "unknown" rows | live |
| Weekend over weekday, 6 to 26 April: all, 1.27.0, 1.26.0 | 0.79, 0.88, 0.52 | 0.786, 0.878, 0.517 | live |
| The same, CI-flagged 1.27.0; uv's 1.27.0 | 0.66; 0.92 | 0.659; 0.924 | recomputed |
| lean-lsp-mcp 0.26.0 and 0.26.1: 8 to 29 April; 8 April to 3 May; 8 April to 10 May | 35,024; 38,953; (40,036 in the table) | 35,024; 38,953; 40,036 | live |
| Their uv, CI and wheel shares | 97.6, 3.5, 98.9, set beside 38,953 | of 40,036: 97.6, 3.5, 98.9; of 38,953: 97.7, 3.3, 99.0; of 35,024: 97.6, 2.7, 98.9 | live and recomputed |
| 1.27.0, 8 to 29 April | 109,023,441 | 109,023,441 | live |
| 1.26.0 on 24 and 25 January | 11.9; 61.7 (1,042,794 of 1,690,307) | 11.86 (188,077 of 1,585,920); 61.69 | recomputed |
| 31 March in three tables | per-day and per-download 6,459,869; by-version 6,524,343 | identical | live |
| pypistats against ClickPy, 25 window days | 17 identical; differences 653 to 104,651; at most 1.0 per cent; ClickPy 0.18 per cent higher summed | 17; 653, 763, 942, 2,145, 72,558, 77,388, 94,019, 104,651; 1.004; 0.18 | recomputed, and live pypistats spot checks on six days |
| The "without mirrors" identity | 22 of 22 days | 22 of 22 (and 0 of 22 without the no-installer exclusion) | recomputed |
| No-installer, named-mirror and Nexus downloads in the window | 255,315; 2,957; 47,834 | identical | recomputed |
| pip's 1.26.0 on 27 March labelled sdist; file-type table sdist that day | 940,901; 1,188 | identical | recomputed |
| uv's 1.26.0 on 26 and 25 March | 7,656,950; 2,911,462 | identical | recomputed |
| pepy: days 2.4 to 7.6 per cent above ClickPy; partial days | 15 days, 22 July to 20 August; four days | 15 (22 July 2.4 to 20 August 5.3, peak 7.6 on 18 August); three days below half plus 13 July | recomputed |
| Cohort window totals | mistral-vibe 2,074,948; others under 43,000; dartlab 17,103; mcp 219,835,062 | identical | data/cohort_window_totals.csv |
| 26 ClickPy queries | 11 exploratory plus 15 scripted | C01 to C12 with C05 in three parts and C06 in two is 15 | scripts/collect_clickpy.py |
Every quotation in sources.md and the record was found on its page (fetched 17:39:48 to 17:39:51 UTC): the packaging guide's "Highly inaccurate" list, "Last updated on Sep 22, 2026", the Linehaul sentence, the Google account and 1 TB sentences, the ClickPy description and the "order of magnitude" note; the BigQuery page's "populated through the Linehaul project" and "Creative Commons License"; pypistats's mirror list (faqs), "retains data for 180 days" (about), the CI/CD sentence, the 01:00 update and "updated once daily" (api); ClickHouse's export sentence, the Null-engine and materialized-view sentences, ifNull(ci, 0) in the view text, the discrepancy and re-ingestion sentences, and the page metadata dates 2026-01-21 and 2026-03-03; the SummingMergeTree sentence "an arbitrary value is selected from the existing ones"; and pepy's "per-version daily breakdown for the last 3 months", the CI-runner sentence and X-API-Key (pepy-api), with "Total installs counted across PyPI mirrors, refreshed once a day" on pepy's front page. The packaging guide writes "pip's" with a curly apostrophe; the record's straight one is a fair transcription. The schema table confirms the installer table's key is (project, version, date, installer) with type outside it, and the file-type table's key includes type.
The illustration
The piece's SVG regenerates byte for byte from scripts/draw_piece_figure.py against data/mcp_daily_by_version_share.csv and the five LH002 commit times. Rendered at 600 by 556, light and dark: the title, subtitle, axis labels, the release line and its time, the two direct labels ("next day: 48%", "peak: 71%"), the five move rows and the two source notes are all legible in both modes, with the bar colour and the text readable on both backgrounds; no label is clipped; no internal id, project name or study number appears in the drawing (searched for LH00, R0, the dependents' names). The desc says what the figure shows and matches the alt text in the piece and the front page in substance. The record's own figure, uptake.svg, renders legibly; it names LH002 and the dependents, which a record may.
The record's own doubts, passed on by the driver
-
Must fix. Header, line 8: "Every source read on 2026-09-26 between 17:13 and 17:23 UTC." data/read_log.csv ends with C12 at 17:25:07. The piece's colophon already says 17:25. One number.
-
Must fix. Findings, "The second hop": "The two were fetched 38,953 times from 8 April to 3 May, the day before 0.26.2: 97.6 per cent by uv, 3.5 per cent flagged as CI, 98.9 per cent as wheels." The three shares are of 40,036 downloads, every download of 0.26.0 and 0.26.1 in the span read, 8 April to 10 May (data/lean_lsp_mcp_0_26_x_breakdown.csv, denominator 40,036). Over 8 April to 3 May they are 97.7, 3.3 and 99.0; over 8 to 29 April, 97.6, 2.7 and 98.9. The text should name the denominator it uses.
-
Must fix. Findings, the same paragraph: "smaller than the day-to-day swing in 1.27.0's own downloads." Over 8 to 29 April the 21 day-to-day changes in 1.27.0's downloads run from 24,974 to 2,743,058, median 407,771 (over 3 to 22 April the median is 582,845, the driver's figure). One of the 21 is below 35,024. The piece's "usually" is right; the record's flat comparative is not.
-
Should fix. The window total differs by table. 219,835,062 in the per-day table, 219,899,536 by version, 219,940,356 by installer and 219,695,030 per download: a spread of 0.11 per cent. The record uses each where its numerator came from that table, and Method says so, but the four figures never appear together and a reader meeting 219,899,536 in the Answer and 219,940,356 in the installer finding will think one is a slip. One sentence in Method, "Choices made", would settle it.
The interpretation boundary
-
Must fix. Piece, line 5: "It shows the new version arriving in days, carried by the programs that install software rather than by any project's decision." The record labels the carrying an interpretation and the piece's own body says "We think that is what most of these downloads were" (line 33) and "on our reading" (line 47). The standfirst says it flat. One clause brings it inside the label.
-
Must fix. README.md, line 5: "It shows new versions carried by installers settling open version ranges, mostly one called uv, rather than by any project's decision." The same verb, and "new versions" in the plural generalises to releases the study did not read by installer: the installer and CI analysis is of 1.27.0 alone, and 1.26.0 was read only for its pace.
-
Must fix. Piece, line 39: "downloads of the new version barely fell at weekends, to 0.88 of the weekday level"; record, "Traffic on the new release barely dips at weekends." The three-week ratio is right, but it is not steady: week by week 1.27.0's weekend-over-weekday ratio is 1.24, 0.91 and 0.62, and without Sunday 12 April, the peak share and the new version's largest day in the first two weeks, the three-week figure is 0.82. In the third week the new version fell at the weekend by more than a third. 1.26.0's ratio is steady (0.55, 0.48, 0.52), so the contrast the piece draws survives; "barely" does not. The record should carry the per-week figures beside the three-week ones, since a reader of the record cannot see the instability from the ratios alone.
-
Note. "we think a bad one would travel as fast" (line 47). The mechanism the piece describes, an installer taking the newest release that fits a range, does not weigh the release's quality, and the sentence is carried as "we think", which is the record's Next entry restated as a scenario. It is within the rules. One qualifier the driver may want: as fast for as long as it stayed on the registry, since a release found bad can be yanked. No change required.
-
Should fix. Piece, line 11: "Each entry names the library, the version, the day". The sentence describes the registry's log; the log keeps a timestamp (L2, L8), and it is the copy read that keeps only the day (record, Limits, "Day, not hour"). Four words make it true of both.
-
Should fix. Piece, line 33: "So a new environment set up on 3 April received 1.27.0 because it existed". No such environment was observed; this is what an installer resolving an open range does. "would have received" keeps the verb honest, as the same construction does at line 43.
-
Should fix. Piece, line 35, and record, "Which installer took it". "Poetry and Bazel are tools that usually install from a lockfile" is true as far as it goes, but the contrast it draws is with uv and pip, and uv keeps a lockfile too (the four LH002 moves the piece counts are uv.lock moves). uv and pip can each resolve afresh or install from a lock, and the log does not say which mode was used. The record's "tools resolving afresh" for uv and pip states as fact what the log cannot show. One sentence in each.
-
Note. The reading of the Poetry/Bazel and CI contrasts. Both are offered as "two things in it fit", and the CI sentence ends "the pattern is the one you would expect if"; the record labels both interpretation. Bazel's 24,660 downloads over twenty days is a small population and the 234 could be a handful of projects; the piece does not lean on it beyond "under 1 per cent". Within the label.
-
Should fix. Piece, line 49: "it cannot tell a person from a build server or an agent". Line 35 has just explained that the flag does tell a build server when the installer reports one. The closing line should not take that back.
Labelling
- Note. The record labels every paragraph (observation, derived measurement, interpretation, and "derived from the sources' stated retention" for the expiry finding), and the piece's verbs carry the same distinctions: "the log names", "it was", "we think", "on our reading", "the pattern is the one you would expect if", "nothing in the log tells them apart". The three places where the verb outruns the label are findings 5, 6 and 10. The piece's one scenario (finding 8) is marked "we think". No sentence in the piece, the short form or the front page claims an installation or a run; the title's "taken up" is qualified in the same breath.
The source-access question
- Sound as handled; one sentence would close it. brief.md records the 403 from github.com for linehaul's source through the session proxy and the decision to take installer behaviour from documentation only; sources.md records that raw.githubusercontent.com answered 200 during a status probe, that neither body was read and the README was deleted unread, and leaves to the driver whether reading it would count as routing around the refusal. The reviewer did not read it either. The handling follows the rule LH002 set for the same proxy ("report such a refusal, not route around it"): raw.githubusercontent.com serves the same repository from the same operator, so reading it is the refused read by another door, and the study is right to have said so rather than done it. The record's Limits say only "linehaul's source on github.com was refused (403)"; a reader of the record alone does not learn that a raw copy was reachable and deliberately not read, which is the more informative fact. One clause pointing to sources.md.
House style and the rules
-
Note. Kept. British spellings throughout the piece, short form, front page and record. No em or en dash in any of the eight files (checked by code point). No internal reference in the piece's prose: "record", "study" and "LH002"/"LH005" appear only in the colophon links, where they belong; none in the short form's body or the front page above the rule; the driver, subagent and issue numbers appear only in the record's header, where they belong. No person's name or handle; no dependent named in the piece, short form, front page or its figure; the library is named as its public address, which the rules allow. Every relative link in the three reader files resolves (checked: 2 in the piece, 1 in the short form, 22 on the front page, none with an anchor). The Draft label is on both bylines and the review lines read "to be filled by the driver". One idea a reader could say back: the download log shows a release taken within days by installers, not by projects' decisions, and shows a download, never an installation or a run. The opening is a moment. Read silently twice; nothing trips except the sentence in finding 13, which reads as taking back line 35.
-
Should fix. README.md, line 38, below the rule. "Its first reading beyond its own machine, of ten projects over four weeks, leads the front page above" no longer describes the page: the download log now leads and the neighbourhood is "the one before it". Below the rule is outside this review's brief, but it contradicts the page it sits on.
-
Note. sources.md S20 quotes "highly inaccurate" in lower case; the page has "Highly inaccurate" at the head of a list item. The record and the piece have the capital. Trivial; the driver may align it.
-
Note. Method, "every count they returned that is used here is repeated by a scripted query". Two things from the exploratory queries are used in sources.md and are not in any retained table: the
pypi.projectsrow namedMCPfrom 2012 (17:19:01) and the server limits (17:17:23). C03 does repeat the absence of anymcprow (data/clickpy_uploads.csv holds 79 lean-lsp-mcp rows and none for mcp). Both are reported with their times in sources.md, which is what the rule asks; the Method sentence is slightly broader than the facts. No change required. -
Note. The front page's row and next question. The new row's subject, instruments and dates are the record's header; "checked against pypistats.org and pepy.tech" is the record's cross-copy finding. "The next question" is the record's first Next entry and the programme's LH006, in the programme's own words about images, layers and build dates; it is a question, not a claim, and it says what it would read. Every sentence of the standfirst is in the piece.
-
Note. The class of claim that needs a person. Nothing in the piece, short form, front page or record says harm is happening now or names a system as compromised. The one scenario sentence (finding 8) is about a mechanism, not an event. Nothing is irreversible outside the repository: the study created no account and read no credential; its reads were anonymous SQL and public API calls.
The queries the reviewer ran
All on 26 September 2026, UTC, through the session proxy. ClickPy as user demo, database pypi, each with FORMAT CSVWithNames.
| Time | Label | Query or fetch | Result |
|---|---|---|---|
| 17:39:44 | V1 | by-version table: date, sum(count), sumIf(count, version='1.27.0') for mcp, 1 to 4 April |
7,788,556/0; 7,351,271/1,639,539; 6,657,180/3,201,463; 5,243,831/2,673,423 |
| 17:39:44 | V2 | window totals with a window function over sum(count) |
refused, ILLEGAL_AGGREGATION (reviewer's syntax); replaced by recomputation from data/ |
| 17:39:45 | V3 | by-version 1.27.0, 8 to 29 April; per-day table, 26 March to 22 April | 109,023,441; 219,835,062 |
| 17:39:45 | I1 | installer table, window, by installer | uv 172,783,051 (78.56); pip 44,872,032 (20.40); poetry 1,788,662; none 255,315; requests 119,237; Nexus 47,834; Bazel 38,023; Browser 31,724 |
| 17:39:45 | I2 | installer table, 3 to 22 April, 1.27.0's share of uv, pip, poetry, Bazel | 58.85; 53.10; 21.23; 0.95 |
| 17:39:45 | I3 | installer table, 3 to 22 April, uv's share of 1.27.0 | 76,466,745 of 94,095,825 (81.26) |
| 17:39:46 | C1 | per-download table, 3 to 22 April, CI-flagged by version class | 1.25.0 59.61; 1.26.0 48.59; 1.27.0 10.58; other 72.90; unknown 0 |
| 17:39:46 | C2 | per-download table, window, CI-flagged | 75,971,844 of 219,695,030 (34.58) |
| 17:39:47 | L1 | per-download table, lean-lsp-mcp 0.26.0 and 0.26.1, 8 April to 10 May, cumulative to 29 April, 3 May, 10 May, with uv, CI and wheel shares | 35,024; 38,953; 40,036; 97.6; 3.5; 98.9 |
| 17:39:47 | W1 | by-version table, 6 to 26 April, weekend mean over weekday mean | 0.786; 0.878; 0.517 |
| 17:39:48 | X1 | 31 March in the per-day, by-version and per-download tables | 6,459,869; 6,524,343; 6,459,869 |
| 17:39:48 | P | https://pypistats.org/api/packages/mcp/overall | 181 days, 29 March to 25 September; six days spot-checked against data/ |
| 17:39:48 to 17:39:51 | L1 to L7 | the eight documentation pages the record cites, and pepy.tech's front page at about 17:41 | all 200; every quotation found |
Recomputed locally from data/ (no fetch): the window totals, the share range and median, the day-to-day changes, the per-week weekend ratios, the CI and uv weekend ratios, the 1.26.0 contrast, the cross-copy counts and the "without mirrors" identity, the pepy comparison, the file-type oddity, the 26 March uv day, and the combined CI share of all versions older than 1.26.0.
Verdict
- articles/what-a-download-shows.md: release after the must-fixes (findings 4, 5 and 7 in the piece). Every count in it reproduces from ClickPy to the digit; every quotation is on its page; every link resolves; the figure regenerates from its script and reads in both modes. The should-fixes are one clause each.
- articles/what-a-download-shows.svg: release as it stands.
- articles/short/what-a-download-shows.md: release as it stands, with the reviewer line filled. Its verbs are already hedged ("we think") where the piece's standfirst is not.
- README.md above the rule: release after finding 6. Finding 17, below the rule, should go in the release commit.
- studies/LH005/LH005.md: correct findings 1, 2, 3, 4 and 7 before the piece cites it as version 0.1; if the driver bumps the record to 0.2 with a Corrections entry, the piece's colophon must follow (R-0004 finding 1 was this exact slip).
- sources.md S20 to S23: release as they stand (finding 18 is optional).
- Nothing in any file falls into the class of claim that AGENTS.md reserves for a person (finding 21).
What the review could not check
- BigQuery itself, for the same reason the study could not: no account. Every figure was checked against ClickPy, which is a copy; agreement between the reviewer's read and the study's read shows the copy was stable across twenty-one minutes, not that it matches the original.
- The 11 exploratory queries and the 17:19:01
pypi.projectsrow namedMCP, which no retained table holds (finding 19). - linehaul's source, pip's and uv's: not read, by the same rule the study followed (finding 15). How each installer fills the installer name and CI flag remains documentation and inference.
- pypistats's and ClickPy's source code (not read by the study either); the "without mirrors" identity is reproduced from the tables, and the second exclusion remains an inference.
- The ClickHouse blog of 27 August 2024 (L5) was not re-fetched; the record takes one sentence from it (the hourly cron job) and says L4 supersedes it.
- The LH002 tables were taken as published, as the record does; R-0004 checked them.
- The review's own cost is not measured here; the driver prices it from the transcript.
Must fix before release
Each item: file, the exact current text, the exact replacement.
-
studies/LH005/LH005.md, header line 8. Current:
Every source read on 2026-09-26 between 17:13 and 17:23 UTC, five to eight months after the eventsReplace with:Every source read on 2026-09-26 between 17:13 and 17:25 UTC, five to eight months after the events -
studies/LH005/LH005.md, Findings, "The second hop cannot be seen in downloads". Current:
The two were fetched 38,953 times from 8 April to 3 May, the day before 0.26.2: 97.6 per cent byuv, 3.5 per cent flagged as CI, 98.9 per cent as wheels.Replace with:The two were fetched 38,953 times from 8 April to 3 May, the day before 0.26.2, and 40,036 times to 10 May, the last day read. Of those 40,036, 97.6 per cent were fetched byuv, 3.5 per cent were flagged as CI and 98.9 per cent were wheels (data/lean_lsp_mcp_0_26_x_breakdown.csv). -
studies/LH005/LH005.md, the same paragraph. Current:
are 0.03 per cent of 1.27.0's 109,023,441, smaller than the day-to-day swing in 1.27.0's own downloads.Replace with:are 0.03 per cent of 1.27.0's 109,023,441, smaller than all but one of the 21 day-to-day changes in 1.27.0's own downloads over those days (the smallest 24,974, the median 407,771). -
articles/what-a-download-shows.md, line 35. Current:
only 11 per cent of the new version's downloads carried it, against 49 per cent of the previous version's and 73 per cent of all older versions'.Replace with:only 11 per cent of the new version's downloads carried it, against 49 per cent of the previous version's and 72 per cent of all older versions' together.And studies/LH005/LH005.md, "Downloads flagged as CI mostly stayed on older versions". Current:against 48.6 per cent of 1.26.0's and 72.9 per cent of every older version's.Replace with:against 48.6 per cent of 1.26.0's, 59.6 per cent of 1.25.0's and 72.9 per cent of every version older than those; all versions older than 1.26.0 together, 71.7 per cent (36,946,018 of 51,507,520). -
articles/what-a-download-shows.md, line 5. Current:
It shows the new version arriving in days, carried by the programs that install software rather than by any project's decision.Replace with:It shows the new version arriving in days, carried, we think, by the programs that install software rather than by any project's decision. -
README.md, line 5. Current:
It shows new versions carried by installers settling open version ranges, mostly one called uv, rather than by any project's decision.Replace with:On our reading it shows the new version carried by installers settling open version ranges, mostly one called uv, rather than by any project's decision. -
articles/what-a-download-shows.md, line 39. Current:
across three whole weeks in April, downloads of the new version barely fell at weekends, to 0.88 of the weekday level, while the old version's fell to about half.Replace with:across three whole weeks in April, downloads of the new version fell less at weekends, to 0.88 of the weekday level, or 0.82 leaving out one unusually busy Sunday, while the old version's fell to about half.And studies/LH005/LH005.md, "People or machines". Current:For 1.27.0 as a whole it was 0.88, and for 1.27.0 fetched byuv, 0.92. Traffic that stays on the old release keeps working hours, as scheduled builds and pinned deployments would. Traffic on the new release barely dips at weekends, and the busiest share of the window fell on Sunday 12 April.Replace with:For 1.27.0 as a whole it was 0.88, and for 1.27.0 fetched byuv, 0.92. The 1.27.0 ratio is not steady: week by week it was 1.24, 0.91 and 0.62, and without Sunday 12 April, the busiest share of the window, the three-week figure is 0.82; 1.26.0's was 0.55, 0.48 and 0.52. Traffic that stays on the old release keeps working hours, as scheduled builds and pinned deployments would. Traffic on the new release dips less at weekends, and the busiest share of the window fell on Sunday 12 April.
Should fix
-
studies/LH005/LH005.md, Method, "Choices made", after
Shares use the ClickPy by-version table's own total as the denominator, so that numerator and denominator come from one table.Insert:The window total therefore differs by table: 219,835,062 in the per-day table, 219,899,536 by version, 219,940,356 by installer and 219,695,030 per download, a spread of 0.11 per cent. -
articles/what-a-download-shows.md, line 11. Current:
Each entry names the library, the version, the day, the installer that asked for the file,Replace with:Each entry names the library, the version, the time (the copy we read keeps only the day), the installer that asked for the file, -
articles/what-a-download-shows.md, line 33. Current:
So a new environment set up on 3 April received 1.27.0 because it existed, whether or not anyone upstream had decided anything.Replace with:So a new environment set up on 3 April would have received 1.27.0 because it existed, whether or not anyone upstream had decided anything. -
articles/what-a-download-shows.md, line 35. Current:
Poetry and Bazel are tools that usually install from a lockfile, which is meant to hold versions still until someone changes them.Replace with:Poetry and Bazel are tools that usually install from a lockfile, which is meant to hold versions still until someone changes them; uv and pip can work either way, and the log does not say which way they were used.And studies/LH005/LH005.md, "Which installer took it". Current:Tools that normally install from a lockfile, such as Poetry and Bazel, took the new release far less than tools resolving afresh, which is what lockfiles are for (interpretation).Replace with:Tools that normally install from a lockfile, such as Poetry and Bazel, took the new release far less thanuvand pip, which can resolve afresh or install from a lockfile; the record does not say which mode a download came from. That is what lockfiles are for (interpretation). -
articles/what-a-download-shows.md, line 49. Current:
it cannot tie one download to another; it cannot tell a person from a build server or an agent.Replace with:it cannot tie one download to another; it cannot tell a person from an agent, and knows a build server only when the installer says so. -
studies/LH005/LH005.md, Limits, "Self-reported fields". Current:
linehaul's source on github.com was refused (403), and pip's anduv's sources were not read.Replace with:linehaul's source on github.com was refused (403) and a raw copy that answered 200 was deliberately not read (sources.md), and pip's anduv's sources were not read. -
README.md, line 38, below the rule. Current:
Its first reading beyond its own machine, of ten projects over four weeks, leads the front page above;Replace with:Its first two readings beyond its own machine, of ten projects over four weeks and of the download log behind them, lead the front page above; -
sources.md, S20 (optional). Current:
calls the counts "highly inaccurate"Replace with:calls the counts "Highly inaccurate"
From notes/R-0005.md in the repository, last changed 26 September 2026.