Skip to content

fix(watcher): keep the startup poll from holding back digests and security intake - #216

Merged
abnegate merged 3 commits into
mainfrom
fix/scheduled-runs-catch-up
Nov 11, 2026
Merged

abnegate merged 3 commits into
mainfrom
fix/scheduled-runs-catch-up

Conversation

@abnegate

Copy link
Copy Markdown
Member

What broke

After the 0.57.5 restart on 2026-11-11, start() awaited a full poll before spawning the loops. That poll ran fix attempts inline from 06:16 until after 07:30, so housekeeping never started. As a result:

Changes

  • Startup: the loops (sources, security intake, housekeeping) start right after warm start, and each runs its first cycle immediately. Retries and cascades now come from the first housekeeping tick instead of a second copy inside the startup poll. poll() remains only as a test driver.
  • Catch-up schedules: ReportSchedule::is_due used to fire only within the exact slot hour. Now a slot stays due for the rest of its UTC day until it runs. A long housekeeping tick or a restart no longer skips it, and a missed slot never fires on a later day.
  • Persisted runs: a new scheduled_runs table (V19) stores each schedule's last run, so a restart neither repeats nor skips a slot. This applies to the PR digest and the repetitive-issues digest.
  • Rate-limit pause: digests now go out while Claude runs are paused for a rate limit, since they make no Claude run.

Tests

Each new test was confirmed to fail without its fix:

  • a_source_blocking_its_thread_never_stalls_security_intake now drives start(). With the startup poll put back, it fails.
  • the_pr_digest_goes_out_while_runs_are_paused_for_a_rate_limit fails if the paused tick continues.
  • a_slot_missed_at_its_hour_runs_later_that_day_only
  • a_restarted_watcher_resumes_the_pr_digest_from_its_last_recorded_run
  • a_scheduled_run_keeps_only_its_latest_time

🤖 Generated with Claude Code

…urity intake

start() awaited a full poll before spawning the loops, so on 2026-11-11 the
startup poll ran fix attempts inline from 06:16 past 07:30 and housekeeping
never started: the 07:00 PR digest was missed and the security inbox was not
polled. The loops now start straight after warm start and each runs its
first cycle immediately; retries and cascades come from the housekeeping
tick instead of a duplicate in the startup poll.

Schedules only fired inside their exact hour and kept their last run in
memory, so a long tick or a restart skipped a slot, and a restart inside
the hour could repeat one. A slot now stays due for the rest of its UTC day
until it runs, and the last run is stored in scheduled_runs so a restart
resumes it. Digests also go out while Claude runs are paused for a rate
limit, since they need no Claude run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@appwrite

appwrite Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

🟢 Tier S · Ready to merge

The watcher starts source polling, security intake, and housekeeping loops immediately after warm start, with each loop running independently. Scheduled reports catch up within their UTC slot day and persist the latest run time, and digest delivery continues during Claude rate-limit pauses. The pull request also adds tests for startup behavior, scheduling, persisted run state, and live poll-cycle telemetry.

Latest changes: The newest commits restore poll-cycle duration telemetry in the live source-poll loop and add a test that verifies the running watcher records it.

Verdict New comments Fixed Still open
✅ Approved 0 0 0
📂 Walkthrough · 12
File Change
crates/claudear-analysis/src/feedback/issue_embeddings.rs Updated the tracker test mock for scheduled-run persistence.
crates/claudear-analysis/src/learning/cluster_detector.rs Updated the tracker test mock for scheduled-run persistence.
crates/claudear-analysis/src/prioritisation/mod.rs Updated the tracker test mock for scheduled-run persistence.
crates/claudear-engine/src/housekeeping.rs Runs housekeeping schedules on immediate ticks, including during Claude rate-limit pauses, and tests retry and slot timing.
crates/claudear-engine/src/watcher.rs Starts independent polling and security loops, persists schedule run times, and records poll-cycle telemetry from live polling.
crates/claudear-engine/src/watcher/security_tests.rs Tests that security intake proceeds when source polling blocks.
crates/claudear-integrations/src/reports/scheduler.rs Keeps report schedules due for the rest of their UTC slot day and applies the weekly lookback guard.
crates/claudear-integrations/src/scm.rs Updated the tracker test mock for scheduled-run persistence.
crates/claudear-storage/src/lib.rs Adds the scheduled-run storage interface.
crates/claudear-storage/src/migrator.rs Registers the scheduled-runs schema migration.
crates/claudear-storage/src/sqlite.rs Implements storage and retrieval of each schedule's latest run time.
migrations/V19__scheduled_runs.sql Creates the table for persisted schedule run times.

Reviewed the commits since 4fcb632 · Details · Comment @appwrite review to re-run, or mention @appwrite with a question.

@appwrite appwrite Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Tier A · See the inline comments. Summary

Comment thread crates/claudear-engine/src/watcher.rs Resolved
abnegate and others added 2 commits November 11, 2026 21:14
… its start

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@appwrite appwrite Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Tier S · Looks good to merge. Summary

@abnegate
abnegate merged commit 8e5e848 into main Nov 11, 2026
19 checks passed
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