Repository navigation
Point old editions to archived pages from their own time - #528
Conversation
utils/wayback.py is now the only code that talks to the Wayback Machine: captures() lists a page's captures through CDX, pick_capture() chooses the last one on or before an edition's end plus 14 days, and save() asks the archive to save a page and reports the real result. archive-new-urls.yml moves its inline Python and curl loop into utils/archive_save.py. It now covers all five URL fields, not only link, and besides URLs new since the last successful run it saves each edition's pages at fixed points: 14 days before the CfP closes and on the day it closes (cfp_ext when set), 30 and 14 days before the start, on the start, and 14 days after it. A run saves every point since the last successful run, each URL once. The old loop reported every save as successful, because `|| true` set the exit status to 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016a2XGgiRrtWm4EUP7ek9wt
A series that serves every edition from one URL shows only its newest edition there, so older editions' links show the wrong one (PyCon Tanzania 2024's sponsor page now shows 2026). utils/archive_resolve.py finds the yearless URLs of superseded editions (ended, with a later edition of the same conference in the data) and replaces each with the CDX capture from that edition's time, written with its full 14-digit timestamp. A URL with no such capture stays as it is and is listed in the rolling PR's NEEDS:archive block. The new weekly archive-resolve.yml also takes over the redirect scan: it requests every live URL once, queues redirects to other sites for the desk as before, archives links that are gone on editions that have ended, and follows moved Mastodon accounts. It writes to the rolling branch with the same merge and push handling as the other writers. The sort no longer touches the network. check_links, check_link_availability, the --skip_links flag, the `pixi run links` task and the no_archive.txt and archived_links.txt caches are removed; the caches were keyed by URL alone, so a miss for one edition hid lookups for every other edition sharing that URL. The enricher's compromise path uses the same CDX rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016a2XGgiRrtWm4EUP7ek9wt
for more information, see https://pre-commit.ci
|
Routine review 1. RequestNo linked issue. The request is the PR body: point superseded editions' yearless URLs (
The 255-URL backfill is announced as a later commit in this PR. 2. Checked against
3. Needs your decision
4. FindingsImportant
Nits
5. TestsInvariant coverage. The request's invariant is "a superseded yearless URL gets the capture from its own edition's time". The tests cover it on the Tanzania fixture ( Base vs change. The new test files import modules that do not exist on base, so they fail there by construction. This proves nothing beyond that. Change (head
6. Bounds
Generated by Claude Code |
requests raises a reset or a connection dropped mid-request as the same ConnectionError as a host that does not resolve, so probe() counted a site that is up but reset one connection as gone, and the weekly resolve would have archived its link for good. probe() now walks the exception chain: a failed TLS handshake, a name-resolution failure or a refused connection is lasting; anything else is "reset" and leaves the link alone. The resolve workflow now replaces NEEDS:archive on every run that finds an open rolling PR, and empties it when nothing is kept, so a week with no data change no longer leaves a stale list. superseded() reads `conference` with .get on both passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016a2XGgiRrtWm4EUP7ek9wt
|
Replies to the routine review. All three are addressed in 608fcdf. Important: a reset counted as broken (fixed). I reproduced it: against a local socket that resets after reading the request,
Nit: Nit: On the decisions:
Full suite: 2628 passed, 4 skipped, 3 xfailed, 2 xpassed. pre-commit is clean on the changed files. Generated by Claude Code |
|
Routine review Re-review of 1. RequestNo linked issue. The request is the PR body: point superseded editions' yearless URLs (
This round's delta (
2. Checked against
3. Needs your decision
4. FindingsImportant None new. Resolved from the first review:
5. TestsInvariant coverage. Unchanged from the first review. The superseded-capture invariant is covered on the Tanzania fixture and on synthetic entries. The 255 real instances are evidenced only once the backfill runs (decision 2). For this round's fix, the invariant is "a ConnectionError that is not lasting never marks a link broken". Base vs change (
Change, full checks (head
6. Bounds
Generated by Claude Code |
Why
Many series serve every edition from one URL, and that URL only shows the newest edition. Older editions in the data still point to it, so they show the wrong edition. PyCon Tanzania 2024's
sponsor(pycon.or.tz/sponsor/) now shows 2026. The data has 255 such URLs, on superseded editions that are already in it. Nothing caught them: the old link checker treated a 200 as healthy, and only replaced links that failed.What changes
utils/wayback.pyis now the only code that talks to the Wayback Machine:captures(url): one CDX request listing a page's successful captures. A failed lookup raisesWaybackErrorinstead of looking like "no captures".pick_capture(stamps, end): the last capture on or before the edition'sendplus 14 days. Applied to Tanzania's real CDX list, this picks 2024-10-04, not the October 2026 capture, which shows the next edition.save(url): asks the archive to save a page and reports the real status.Saving:
archive-new-urls.yml→utils/archive_save.py. The triggers are the same as before. It saves URLs new since the last successful run, now from all five URL fields instead of onlylink. It also saves each edition's pages at fixed points, so a capture from the right time exists before the site moves on:cfp_extwhen set)start, onstart, and 14 days after itA run covers every point since the last successful run and saves each URL once. The old loop reported every save as successful, because
|| truemade the exit status 0.Resolving: the new weekly
archive-resolve.yml→utils/archive_resolve.py.conferenceis in the data. Each yearless live URL on it gets the chosen capture, written with its full 14-digit timestamp.NEEDS:archiveblock of the rolling PR. The replacements are listed in the commit body, andCOMMITTED:archivenames the commit.2024.pycon.de), editions that aren't superseded, and the 872 existing archive links.redirect-scan.yml, which this PR removes: every live URL is requested once, and redirects to other sites are queued for the desk as before. Moved Mastodon accounts are followed.auto/conference-updateswith the same concurrency group,merge_data.pyconflict handling and push retries as the other writers.The sort never touches the network. Removed:
check_linksandcheck_link_availability--skip_links, and thepixi run linkstaskno_archive.txtandarchived_links.txtcaches. Both were keyed by URL alone, so a miss recorded for one edition blocked the lookup for every other edition sharing that URL. They also had no dates, so they couldn't say which edition a capture showed.Docs:
.claude/skills/enricher/SKILL.md) uses the same CDX query and rule.AGENTS.md,REVIEW.mdandDEVELOPMENT.mdno longer mention--skip_links.desk.mdnames the newarchivewriter's blocks.Still to come in this PR
The one-time backfill of the 255 superseded URLs. It needs Wayback access, which the cloud session that wrote this PR didn't have. It will be a separate commit, run with
archive_resolve.py --no-probe, so its diff can be reviewed by itself.Tests
pytest tests/(the uv command from REVIEW.md): 2,623 passed, 4 skipped, 3 xfailed, 2 xpassed.tests/test_wayback.py,tests/test_archive_save.py,tests/test_archive_resolve.py.tests/test_link_redirects.pynow runs the redirect cases through the weekly link check. The tests for the removed cache-based checker (tests/test_link_checking.py) are removed with it.ruff@0.4.4,black@24.4.2,isort@5.13.2anddocsig@0.53.2, with the pre-commit arguments, are clean on the changed files.python utils/sort_yaml.pyon the current data succeeds. Its only diff is three editions moving toarchive.ymlby date, which isn't committed here.The two workflows haven't run yet.
archive-resolve.ymlcan only be dispatched once it's onmain.Generated by Claude Code