Overview
The #papers digest silently drops strong-lensing papers. Two were missed on 2026-07-15 (2607.12129, a lensed-arc candidate in MACS J0308.9+2645; 2607.12209, the NGC 6505 Einstein ring OSN recovery test). The keyword query is not at fault — re-running arxiv_fetch.py with LOOKBACK_HOURS=72 returns both. The window is anchored to submission time, but the arXiv search API only indexes a paper once it is announced, 1–3 days later. Every run therefore has a permanently-dropped tail, worst on Mon/Tue.
Plan
- Replace the rolling "last N hours" window with arXiv's announcement bands, so each run selects exactly the batch that just became searchable.
- Compute the band from the run time: find the most recent 20:00 ET announcement (Sun–Thu), take the latest 14:00 ET submission deadline at or before it as the band end, and the previous deadline as the band start.
- Derive the ET↔UTC offset with
zoneinfo rather than hard-coding it, so the band stays correct across DST.
- Drop the Mon-72h / weekday-24h branch in the workflow — the band logic subsumes it, including the 3-day Fri→Mon weekend band.
- Keep
lookback_hours as a manual-dispatch escape hatch for test-fires and for a one-off backfill of already-dropped papers.
- Add a
--selftest mode covering the weekday and DST cases, and correct the docstring's "gapless" rationale to name the announcement anchor.
Detailed implementation plan
Affected Repositories
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoMind |
main |
clean |
Suggested branch: feature/arxiv-digest-announcement-window
Worktree: ~/Code/PyAutoLabs-wt/arxiv-digest-announcement-window/. A worktree is used deliberately so PyAutoMind's main checkout stays on main for registry operations — prompt_sync_push runs git add -A on whatever branch is checked out, so editing Mind's own CI on a branch in the main checkout would commit registry state to the feature branch.
The bug
.github/scripts/arxiv_fetch.py:77 keeps papers whose <published> (v1 submission timestamp) is within LOOKBACK_HOURS of now. Both missed papers were submitted Mon 2026-07-13 at 20:24 and 23:18 UTC — after the Mon 14:00 ET cut-off — so they entered the Tue 20:00 ET announcement batch and became searchable at 00:00 UTC Wed. Wednesday's 02:00 UTC run looked back 24 h to Tue 02:00 UTC; their Monday timestamps fall ~3 h the wrong side of that boundary. Tuesday's run could not have seen them either (not yet announced).
The docstring's claim that consecutive runs "cover disjoint day-bands (gapless)" only holds if papers are searchable at submission. They are not:
| Run (02:00 UTC) |
Window queried (by submission) |
Batch actually announced by then |
Gap |
| Tue (24 h) |
Mon 02:00 → Tue 02:00 |
Fri 18:00 → Mon 18:00 UTC |
misses Fri 18:00 → Mon 02:00 |
| Wed–Fri (24 h) |
prev 02:00 → 02:00 |
prev-day 18:00 → 18:00 UTC |
misses the 18:00 → 02:00 tail |
| Mon (72 h) |
Fri 02:00 → Mon 02:00 |
Thu 18:00 → Fri 18:00 UTC |
sweeps three days not yet announced |
Monday's 72 h "weekend sweep" is the clearest case: weekend submissions are not announced until Mon 20:00 ET — after Monday's run — and Tuesday's 24 h window has already moved past them.
arXiv's actual schedule
Announcements fire 20:00 ET, Sun–Thu. Submission deadlines are 14:00 ET, Mon–Fri. Each announcement covers submissions between the previous deadline and its own:
| Submitted between (ET) |
Announced (ET) |
| Mon 14:00 → Tue 14:00 |
Tue 20:00 |
| Tue 14:00 → Wed 14:00 |
Wed 20:00 |
| Wed 14:00 → Thu 14:00 |
Thu 20:00 |
| Thu 14:00 → Fri 14:00 |
Sun 20:00 |
| Fri 14:00 → Mon 14:00 |
Mon 20:00 |
The 02:00 UTC cron lands at 21:00–22:00 ET the previous day — just after that day's 20:00 ET announcement. So the Mon–Fri runs pick up the bands Thu→Fri, Fri→Mon, Mon→Tue, Tue→Wed, Wed→Thu. Their union is exactly one week with no overlap: disjoint and gapless, for real this time.
Implementation Steps
.github/scripts/arxiv_fetch.py — add a pure announcement_band(now: datetime) -> tuple[datetime, datetime]:
- convert
now to ZoneInfo("America/New_York");
- walk back to the most recent 20:00 ET on a Sun–Thu at or before it;
band_end = latest Mon–Fri 14:00 ET at or before that announcement (Sunday announcements resolve to Fri 14:00);
band_start = the previous Mon–Fri 14:00 ET before band_end (Monday resolves back to Friday, giving the 3-day weekend band);
- return both as UTC.
- Replace the
since/ts < since filter with band_start < ts <= band_end. Keep the <published> (v1) basis so v2 revisions still do not resurface.
- Keep
LOOKBACK_HOURS as an explicit override: when set and non-empty, use the legacy rolling window (manual test-fires and the backfill). When unset, use the band. Record which mode ran in the JSON.
- Widen
max_results 100 → 200 — the 3-day weekend band is the largest, and the cap is applied before band selection.
- Extend the output JSON with
mode, band_start, band_end alongside the existing keys; keep since/until populated so the downstream Claude and Slack steps are untouched.
.github/workflows/arxiv_papers.yml — delete the dow/72h/24h branch; pass LOOKBACK_HOURS only when the dispatch override is non-empty. Update the timing comment block to describe the announcement anchor.
- Add
--selftest to arxiv_fetch.py: table-driven asserts over each weekday run, both DST regimes (a July run at UTC-4 and a January run at UTC-5), the weekend band, and the two missed papers as a regression case (Mon 20:24 UTC must fall inside the band a Wed 02:00 UTC run computes). Run it as a workflow step before the fetch.
- Rewrite the module docstring: the window is announcement-anchored; state why submission-anchored windows drop papers.
Backfill
After merge, one manual workflow_dispatch with lookback_hours=168 to sweep the week and recover what the current windows dropped. This runs the normal Claude + Slack path, so it posts a catch-up digest to #papers.
Testing
python3 .github/scripts/arxiv_fetch.py --selftest — band maths, no network.
- A live run against the real API for the current band, checking both missed papers appear when the clock is faked to Wed 2026-07-15 02:00 UTC.
workflow_dispatch test-fire with an override to confirm the override path is intact.
Key Files
.github/scripts/arxiv_fetch.py — window logic, band function, selftest
.github/workflows/arxiv_papers.yml — lookback branch removal, selftest step, timing comment
Trade-offs
- Band vs. state. A cross-run "seen IDs" store would also fix this, but it trades the current stateless design for a committed state file and its drift modes. The band keeps statelessness and gets exact disjointness rather than dedup-after-overlap.
- Residual. Papers announced out of band (submission on hold, a cross-list added later) are still missed. Rare; a seen-ID store is the only real fix and is not worth it yet.
- Jitter. GitHub cron only ever fires late. The band is stable anywhere from 20:00 ET to the next 20:00 ET, so it absorbs ~22 h of slip — far more tolerance than the ±0 the current rolling window really had.
Original Prompt
Click to expand starting prompt
arXiv #papers digest silently drops papers — window anchored to submission, not announcement
Type: bug
Target: pyautomind
Repos:
- PyAutoMind
Difficulty: medium
Autonomy: safe
Priority: normal
Status: formalised
The #papers digest missed two strong-lensing papers announced on 2026-07-15
(arXiv:2607.12129, a lensed-arc candidate in MACS J0308.9+2645; arXiv:2607.12209,
the NGC 6505 Einstein ring OSN recovery test). Both are matched by the keyword
query — re-running .github/scripts/arxiv_fetch.py with LOOKBACK_HOURS=72
returns both — so the recall-first QUERY is not at fault.
Root cause: arxiv_fetch.py:77 keeps papers whose <published> (v1 submission
timestamp) falls within LOOKBACK_HOURS of now, but the arXiv search API only
indexes a paper once it is announced, which is 1–3 days after submission.
Both papers were submitted Mon 2026-07-13 at 20:24 and 23:18 UTC — after the
Mon 14:00 ET cut-off — so they went into the Tue 20:00 ET announcement batch and
became searchable at 00:00 UTC Wed 2026-07-15. Wednesday's 02:00 UTC run looked
back 24 h to Tue 02:00 UTC; their Monday timestamps fall ~3 h the wrong side of
that boundary. Tuesday's run could not have seen them either (not yet announced).
Permanently dropped, with no error and no gap in the heartbeat.
The module docstring's claim that consecutive runs "cover disjoint day-bands
(gapless)" only holds if papers are searchable at submission time. They are not,
so every run has a dropped tail, and Monday/Tuesday are worst:
| Run (02:00 UTC) |
Window queried (by submission) |
Batch actually announced by then |
Gap |
| Tue (24 h) |
Mon 02:00 → Tue 02:00 |
Fri 18:00 → Mon 18:00 UTC |
misses Fri 18:00 → Mon 02:00 |
| Wed–Fri (24 h) |
prev 02:00 → 02:00 |
prev-day 18:00 → 18:00 UTC |
misses the 18:00 → 02:00 tail |
| Mon (72 h) |
Fri 02:00 → Mon 02:00 |
Thu 18:00 → Fri 18:00 UTC |
sweeps three days not yet announced |
Monday's 72 h "weekend sweep" is the clearest illustration: weekend submissions
are not announced until Mon 20:00 ET — after Monday's run — and Tuesday's 24 h
window has already moved past them.
Fix: anchor the window to arXiv's announcement bands rather than a rolling
"last N hours", preserving the existing stateless disjoint-band design and its
jitter tolerance; only the band edges change. At a 02:00 UTC run the freshly
announced batch is submissions from roughly 32 h to 8 h ago; the Monday run needs
the three-day Fri 14:00 ET → Mon 14:00 ET band. The ET→UTC offset shifts by an
hour across DST (14:00 ET = 18:00 UTC in EDT, 19:00 UTC in EST) and must be
computed, not hard-coded. Update the docstring's gapless-band rationale to state
the announcement anchor. Include a one-off backfill run to recover papers the
current windows have already dropped.
Overview
The #papers digest silently drops strong-lensing papers. Two were missed on 2026-07-15 (2607.12129, a lensed-arc candidate in MACS J0308.9+2645; 2607.12209, the NGC 6505 Einstein ring OSN recovery test). The keyword query is not at fault — re-running
arxiv_fetch.pywithLOOKBACK_HOURS=72returns both. The window is anchored to submission time, but the arXiv search API only indexes a paper once it is announced, 1–3 days later. Every run therefore has a permanently-dropped tail, worst on Mon/Tue.Plan
zoneinforather than hard-coding it, so the band stays correct across DST.lookback_hoursas a manual-dispatch escape hatch for test-fires and for a one-off backfill of already-dropped papers.--selftestmode covering the weekday and DST cases, and correct the docstring's "gapless" rationale to name the announcement anchor.Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch:
feature/arxiv-digest-announcement-windowWorktree:
~/Code/PyAutoLabs-wt/arxiv-digest-announcement-window/. A worktree is used deliberately so PyAutoMind'smaincheckout stays onmainfor registry operations —prompt_sync_pushrunsgit add -Aon whatever branch is checked out, so editing Mind's own CI on a branch in the main checkout would commit registry state to the feature branch.The bug
.github/scripts/arxiv_fetch.py:77keeps papers whose<published>(v1 submission timestamp) is withinLOOKBACK_HOURSof now. Both missed papers were submitted Mon 2026-07-13 at 20:24 and 23:18 UTC — after the Mon 14:00 ET cut-off — so they entered the Tue 20:00 ET announcement batch and became searchable at 00:00 UTC Wed. Wednesday's 02:00 UTC run looked back 24 h to Tue 02:00 UTC; their Monday timestamps fall ~3 h the wrong side of that boundary. Tuesday's run could not have seen them either (not yet announced).The docstring's claim that consecutive runs "cover disjoint day-bands (gapless)" only holds if papers are searchable at submission. They are not:
Monday's 72 h "weekend sweep" is the clearest case: weekend submissions are not announced until Mon 20:00 ET — after Monday's run — and Tuesday's 24 h window has already moved past them.
arXiv's actual schedule
Announcements fire 20:00 ET, Sun–Thu. Submission deadlines are 14:00 ET, Mon–Fri. Each announcement covers submissions between the previous deadline and its own:
The 02:00 UTC cron lands at 21:00–22:00 ET the previous day — just after that day's 20:00 ET announcement. So the Mon–Fri runs pick up the bands Thu→Fri, Fri→Mon, Mon→Tue, Tue→Wed, Wed→Thu. Their union is exactly one week with no overlap: disjoint and gapless, for real this time.
Implementation Steps
.github/scripts/arxiv_fetch.py— add a pureannouncement_band(now: datetime) -> tuple[datetime, datetime]:nowtoZoneInfo("America/New_York");band_end= latest Mon–Fri 14:00 ET at or before that announcement (Sunday announcements resolve to Fri 14:00);band_start= the previous Mon–Fri 14:00 ET beforeband_end(Monday resolves back to Friday, giving the 3-day weekend band);since/ts < sincefilter withband_start < ts <= band_end. Keep the<published>(v1) basis so v2 revisions still do not resurface.LOOKBACK_HOURSas an explicit override: when set and non-empty, use the legacy rolling window (manual test-fires and the backfill). When unset, use the band. Record which mode ran in the JSON.max_results100 → 200 — the 3-day weekend band is the largest, and the cap is applied before band selection.mode,band_start,band_endalongside the existing keys; keepsince/untilpopulated so the downstream Claude and Slack steps are untouched..github/workflows/arxiv_papers.yml— delete thedow/72h/24h branch; passLOOKBACK_HOURSonly when the dispatch override is non-empty. Update the timing comment block to describe the announcement anchor.--selftesttoarxiv_fetch.py: table-driven asserts over each weekday run, both DST regimes (a July run at UTC-4 and a January run at UTC-5), the weekend band, and the two missed papers as a regression case (Mon 20:24 UTC must fall inside the band a Wed 02:00 UTC run computes). Run it as a workflow step before the fetch.Backfill
After merge, one manual
workflow_dispatchwithlookback_hours=168to sweep the week and recover what the current windows dropped. This runs the normal Claude + Slack path, so it posts a catch-up digest to #papers.Testing
python3 .github/scripts/arxiv_fetch.py --selftest— band maths, no network.workflow_dispatchtest-fire with an override to confirm the override path is intact.Key Files
.github/scripts/arxiv_fetch.py— window logic, band function, selftest.github/workflows/arxiv_papers.yml— lookback branch removal, selftest step, timing commentTrade-offs
Original Prompt
Click to expand starting prompt
arXiv #papers digest silently drops papers — window anchored to submission, not announcement
Type: bug
Target: pyautomind
Repos:
Difficulty: medium
Autonomy: safe
Priority: normal
Status: formalised
The #papers digest missed two strong-lensing papers announced on 2026-07-15
(arXiv:2607.12129, a lensed-arc candidate in MACS J0308.9+2645; arXiv:2607.12209,
the NGC 6505 Einstein ring OSN recovery test). Both are matched by the keyword
query — re-running
.github/scripts/arxiv_fetch.pywith LOOKBACK_HOURS=72returns both — so the recall-first
QUERYis not at fault.Root cause:
arxiv_fetch.py:77keeps papers whose<published>(v1 submissiontimestamp) falls within
LOOKBACK_HOURSof now, but the arXiv search API onlyindexes a paper once it is announced, which is 1–3 days after submission.
Both papers were submitted Mon 2026-07-13 at 20:24 and 23:18 UTC — after the
Mon 14:00 ET cut-off — so they went into the Tue 20:00 ET announcement batch and
became searchable at 00:00 UTC Wed 2026-07-15. Wednesday's 02:00 UTC run looked
back 24 h to Tue 02:00 UTC; their Monday timestamps fall ~3 h the wrong side of
that boundary. Tuesday's run could not have seen them either (not yet announced).
Permanently dropped, with no error and no gap in the heartbeat.
The module docstring's claim that consecutive runs "cover disjoint day-bands
(gapless)" only holds if papers are searchable at submission time. They are not,
so every run has a dropped tail, and Monday/Tuesday are worst:
Monday's 72 h "weekend sweep" is the clearest illustration: weekend submissions
are not announced until Mon 20:00 ET — after Monday's run — and Tuesday's 24 h
window has already moved past them.
Fix: anchor the window to arXiv's announcement bands rather than a rolling
"last N hours", preserving the existing stateless disjoint-band design and its
jitter tolerance; only the band edges change. At a 02:00 UTC run the freshly
announced batch is submissions from roughly 32 h to 8 h ago; the Monday run needs
the three-day Fri 14:00 ET → Mon 14:00 ET band. The ET→UTC offset shifts by an
hour across DST (14:00 ET = 18:00 UTC in EDT, 19:00 UTC in EST) and must be
computed, not hard-coded. Update the docstring's gapless-band rationale to state
the announcement anchor. Include a one-off backfill run to recover papers the
current windows have already dropped.