Skip to content

feat(review): add hourly sweep-liveness watchdog with self-heal re-enqueue#3835

Merged
JSONbored merged 1 commit into
mainfrom
feat/sweep-liveness-watchdog
Jul 6, 2026
Merged

feat(review): add hourly sweep-liveness watchdog with self-heal re-enqueue#3835
JSONbored merged 1 commit into
mainfrom
feat/sweep-liveness-watchdog

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • Adds a self-heal watchdog for the scheduled regate sweep (flag-gated by GITTENSORY_SWEEP_WATCHDOG, default OFF): an hourly cron job scans the SAME acting-autonomy repo set the sweep itself covers (mirrors fanOutAgentRegateSweepJobs's own repo-selection exactly), and for any INSTALLED repo that has open PRs but whose last_regated_at marker hasn't advanced within a 45-minute staleness window, it:
    1. Emits a structured sweep_liveness_stale log at level: "error" (Sentry-visible, same convention as ops_anomaly and every other Sentry-forwarded anomaly signal in this codebase).
    2. Re-enqueues a single targeted agent-regate-sweep for just that repo — the exact same message shape the normal fan-out sends, so this is a pure nudge, never a bypass of the sweep's own gating/dedup/backpressure logic.
  • A registered-but-uninstalled repo is never watched (mirrors fix(review): skip open-PR refresh for uninstalled registry repos in the regate sweep #3797/#sweep-uninstalled-budget-waste) — it never gets a per-PR fan-out regardless of installation status, so flagging it would just spend the shared GITHUB_PUBLIC_TOKEN budget on a sweep that can never act.
  • Fails safe at both levels: a per-repo error (a transient D1 read) is logged and the scan continues to the next repo; a total scan failure (e.g. listRepositories itself failing) is logged and the function returns an empty result rather than throwing into the queue.
  • New sweep-liveness-watchdog job type, wired end-to-end: types.ts (JobMessage variant), wrangler.jsonc/worker-configuration.d.ts (the new flag, regenerated via cf-typegen), env.d.ts (the widened-to-string test/runtime override, matching every other togglable flag's own override entry), src/index.ts (hourly cron enqueue, flag-gated), src/queue/processors.ts (the job handler), src/selfhost/maintenance-admission.ts (registered as a deferrable maintenance job type, same lane as ops-alerts).

This directly answers the "we should never have to nudge this system, it should just work on its own even after restarts" ask from today's incident retro, and is the concrete self-heal counterpart to #3807's fan-out isolation fix.

Closes #3808.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes. (Touches several files because a brand-new job type requires wiring at every one of its standard touch points, per this repo's own per-job-type checklist.)
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked an issue, or this is small enough that the summary explains why an issue is not needed.

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck
  • npm run test:coverage locally; codecov/patch requires ≥99% coverage of the lines AND branches you changed (aim for 100% on your diff so CI variance does not fail near the threshold). Global coverage is a non-blocking trend with a loose 90% backstop, not the gate.
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics. (This feature emits internal structured logs only — no public GitHub-facing surface.)
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests. (N/A — no auth/session/CORS surface touched.)
  • API/OpenAPI/MCP behavior is updated and tested where needed. (N/A — no API/OpenAPI/MCP surface changed; this is an internal queue job.)
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks. (N/A — backend-only change, no UI touched.)
  • Visible UI changes include a UI Evidence section below. (N/A — no visible UI change.)
  • Public docs/changelogs are updated where needed; changelogs are only edited for release-prep PRs.

Notes

  • Flag defaults to OFF, matching every other convergence capability's own default-OFF convention (*-wire.ts pattern) — this PR's deploy is byte-identical until the flag is explicitly set.

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 6, 2026
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.53%. Comparing base (7d145f0) to head (3094d0d).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3835   +/-   ##
=======================================
  Coverage   93.53%   93.53%           
=======================================
  Files         336      337    +1     
  Lines       33281    33324   +43     
  Branches    12175    12189   +14     
=======================================
+ Hits        31128    31171   +43     
  Misses       1528     1528           
  Partials      625      625           
Files with missing lines Coverage Δ
src/index.ts 94.80% <100.00%> (+0.06%) ⬆️
src/queue/processors.ts 94.52% <100.00%> (+<0.01%) ⬆️
src/review/sweep-watchdog.ts 100.00% <100.00%> (ø)
src/selfhost/maintenance-admission.ts 100.00% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@loopover-orb

loopover-orb Bot commented Jul 6, 2026

Copy link
Copy Markdown

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-06 21:29:10 UTC

11 files · 1 AI reviewer · no blockers · readiness 100/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review: This PR changes guardrail-protected path(s): src/selfhost/maintenance-admission.ts (matched src/selfhost/**), wrangler.jsonc (matched wrangler.jsonc), wrangler.jsonc (matched **/wrangler.jsonc).

Review summary
This PR adds a flag-gated hourly watchdog that detects repos whose regate sweep marker has gone stale despite open PRs, logs a structured Sentry-visible event, and re-enqueues a single targeted `agent-regate-sweep` job for that repo. The staleness logic (`isSweepStale`), repo selection mirroring `fanOutAgentRegateSweepJobs`, and fail-safe error handling (per-repo and top-level) are all correct and well-tested, and the new job type is wired consistently across types.ts, processors.ts, index.ts cron, maintenance-admission.ts, wrangler.jsonc, env.d.ts, and worker-configuration.d.ts. The feature is default-OFF and the diff is internally coherent with its description; the main open question is whether the linked issue (#3808) actually authorizes this scope, which the external brief flags as only partially matched.

Nits — 7 non-blocking
  • src/review/sweep-watchdog.ts: the per-repo scan body nests to depth 5 (try → for → try → if chains); consider extracting the per-repo check into a small named function for readability.
  • src/review/sweep-watchdog.ts (errorMessage(...).slice(0, 200)): the 200-char truncation is a magic number reused twice with no named constant or comment explaining the choice.
  • watchedRepos() in sweep-watchdog.ts silently swallows resolveRepositorySettings errors per-repo with only a comment, no log line — worth at least a console.error like the other failure paths so a persistent settings-resolution failure isn't invisible.
  • Confirm the linked issue (feat(observability): per-repo sweep-liveness watchdog with Sentry/Prometheus alerting and automatic targeted re-enqueue self-heal #3808) actually scopes this exact watchdog design — the external brief notes only partial title-match coverage, and this repo's convention requires every contributor PR to close/link an eligible issue precisely.
  • Consider batching countOpenPullRequests/getLatestRegatedAt across the watched repo set (e.g. a single query keyed by repo) rather than two D1 round-trips per repo in the loop — currently bounded and fine at present repo-count scale, but worth revisiting if the acting-autonomy repo set grows significantly.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.
  • Touches a guarded path — held for manual review — A maintainer must review and merge this change.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #3808
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 51 registered-repo PR(s), 43 merged, 372 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 51 PR(s), 372 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 51 PR(s), 372 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

…queue (#3808)

Nothing previously noticed when the scheduled regate sweep stopped
advancing a repo's last-regated marker -- the 2026-07-06 incident stayed
silent for hours until a human queried the database directly.

Add an hourly watchdog (flag-gated by GITTENSORY_SWEEP_WATCHDOG, default
OFF) that scans the same acting-autonomy repo set the sweep itself
covers. A repo with open PRs whose sweep marker hasn't advanced within a
45-minute window gets a structured sweep_liveness_stale log (Sentry-
visible) and a single targeted agent-regate-sweep re-enqueue -- the same
message shape the normal fan-out sends, so this only nudges the existing
sweep rather than bypassing its own gating/dedup logic. A registered-but-
uninstalled repo is never watched, since it can never get a per-PR
fan-out regardless of nudging. Fails safe per-repo and at the top level.
@JSONbored
JSONbored force-pushed the feat/sweep-liveness-watchdog branch from 36c4b12 to 3094d0d Compare July 6, 2026 21:19
@JSONbored
JSONbored merged commit 338952c into main Jul 6, 2026
11 checks passed
@JSONbored
JSONbored deleted the feat/sweep-liveness-watchdog branch July 6, 2026 21:55
JSONbored added a commit that referenced this pull request Jul 16, 2026
…pinned wrangler

The previous commit's regeneration silently picked up a stale, globally-installed
wrangler (4.103.0, bundling workerd@1.20260617.1) instead of this repo's pinned
4.107.0 (workerd@1.20260701.1) -- node_modules/.bin/wrangler didn't exist yet at
that point (fresh worktree, npm ci hadn't run), so `wrangler types` fell through
to PATH resolution and found /opt/homebrew/bin/wrangler instead. Not an actual
repo-side drift issue: a clean npm ci + regeneration in a fresh worktree confirms
origin/main's worker-configuration.d.ts is (and has been) correctly in sync since
#3764 -- every commit back through #3835 already references workerd@1.20260701.1.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. manual-review Gittensor contributor context

Development

Successfully merging this pull request may close these issues.

feat(observability): per-repo sweep-liveness watchdog with Sentry/Prometheus alerting and automatic targeted re-enqueue self-heal

1 participant