Skip to content

fix(catchup): self-heal a future-parked mention-catchup cursor (#396) - #397

Open
DipeshRajoria007 wants to merge 1 commit into
mainfrom
fix/mention-catchup-cursor-skew
Open

fix(catchup): self-heal a future-parked mention-catchup cursor (#396)#397
DipeshRajoria007 wants to merge 1 commit into
mainfrom
fix/mention-catchup-cursor-skew

Conversation

@DipeshRajoria007

Copy link
Copy Markdown
Collaborator

What & why

Fixes the cursor half of #396. miniOG's missed-mention catch-up scanner parked its cursor in the future on a system-clock skew and never recovered, so it silently stopped recovering mentions. In the incident (thread 1782110778.388229) a @miniOG please review these prs request created no job and got no reply.

Root cause

mentionCatchup.ts advanced the cursor with Math.max(nowTs, maxSeenTs), and the cursor only ever moves forward. A clock jump into the future (this box's clock bounces) — or a future-dated message via maxSeenTs — latched mention_catchup_cursor_ts ~5.5 days ahead (observed value 1782634754 → 2026-06-28, written 06-22 20:43). Each scan starts at oldest = cursor - 5, so a future cursor makes conversations.history skip every real message until wall-clock time catches up. Nothing reset it → multi-day blackout.

Change (sidecar/src/slack/mentionCatchup.ts)

  • effectiveOldestTs(storedCursor, nowTs, lookbackSeconds) — when the stored cursor is ahead of nowTs (or non-finite/≤0), fall back to the lookback window so the scanner self-heals once the clock normalizes; otherwise resume at storedCursor - 5. Logs a WARN when a future cursor is detected.
  • Advance the cursor to nowTs only (dropped maxSeenTs) so a stray future-dated message can't ratchet it past real time.

Tests

sidecar/tests/mentionCatchupHistory.test.ts (+4) cover effectiveOldestTs: sane resume (cursor-5), unset → lookback, future-parked cursor → lookback (self-heal), non-finite → lookback.

All 843 sidecar tests pass; build, eslint (zero-warning), prettier green.

Out of scope (tracked in #396)

  • Catch-up scans conversations.history, which doesn't return non-broadcast thread replies — so a missed mention posted as a thread reply (this incident) still can't be recovered even with a healthy cursor. Needs conversations.replies over recently-active threads.
  • Live Socket Mode staleness/heartbeat — the WebSocket dying on the same skew while the process stays up is the other half of the outage.

Closes part of #396.

🤖 Generated with Claude Code

… skew)

The mention-catchup recovery scanner advanced its cursor with
`Math.max(nowTs, maxSeenTs)` and the cursor only ever moves forward. A single
system-clock jump into the future (this environment's clock bounces) — or a
future-dated message — parked `mention_catchup_cursor_ts` days ahead of real
time. Since each scan starts at `oldest = cursor - 5`, a future cursor makes
the scan skip every real message until the wall clock catches up, silently
blinding catch-up. Combined with the live Socket Mode connection dying on the
same skew, miniOG dropped every mention for the gap — including a
"please review these prs" request that never created a job (thread
1782110778.388229).

- Add `effectiveOldestTs()`: when the stored cursor is ahead of `nowTs` (or
  non-finite/unset), fall back to the lookback window so the scanner self-heals
  once the clock normalizes, instead of staying blind.
- Advance the cursor to `nowTs` only (drop maxSeenTs) so a future-dated message
  can't ratchet it past real time.
- Tests for effectiveOldestTs (sane resume, unset fallback, future-cursor
  self-heal, non-finite).

Follow-up (separate issue): catch-up scans conversations.history, which does
not return thread replies, so a missed mention posted as a thread reply still
can't be recovered even with a healthy cursor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant