feat(watchdog): B15 watchdog dashboard tile #442
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!442
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "dev/431"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Adds
GET /watchdog/statusand operator action endpoints for the B15 visibility layer over B10/B12/B14 hardening signals.Test plan
just qaclean (typecheck, Biome lint/format, 54 server tests pass)GET /watchdog/statusreturns empty shape on a fresh DBrecordDeadLetterPr()surfaces it in the responsePOST /watchdog/retryremoves the entry;POST /watchdog/snoozesetssnoozed_until~24 h out/agentspage shows 🟢 empty state when no signals are activeCloses #431
New `GET /watchdog/status` endpoint aggregates the three hardening signal classes: dead-letter PRs (B10), worktree-recovery branches (B12), and daily counters for session-resume failures (B14) + dev→boss escalations (B11). Operator action surface: - `POST /watchdog/retry/:repo/:number` — clears dead-letter row. - `POST /watchdog/snooze/:repo/:number` — suppresses alerts for 24 h. - `GET /watchdog/recovery/diff` — git show for a stash branch. - `DELETE /watchdog/recovery` — force-delete stash branch. Persistence: three new SQLite tables (`watchdog_dead_letters`, `watchdog_recoveries`, `watchdog_counters`) survive restarts. An in-process SSE listener bridges future `flow:dead-letter` events from B10 into the DB without a code change. Frontend: `WatchdogPanel` on `/agents` polls every 30 s, shows a 🟢 empty state when clean, and surfaces stacked rows (dead-letters + recoveries + counters) with Retry / Snooze / Inspect / Drop buttons. Inspect opens a slide-out drawer with the full git diff. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>499a1ee3c14c3d0caebeBackend is clean — DB schema, route logic, and server tests are all solid. One AC requirement is missing:
apps/web/src/components/watchdog-panel.tsx): The issue AC requires "Frontend test: empty state renders; populated state renders all 3 rows; Retry button POSTs to/watchdog/retry/<pr>". No frontend test file was added in this PR. Please add a test (e.g.watchdog-panel.test.tsx) covering at minimum: (1) empty state rendersdata-testid="watchdog-empty", (2) populated state showsdead-letter-cardandrecovery-cardelements, (3) clicking Retry callsPOST /watchdog/retry/<repo>/<number>.Nit (not blocking):
GET /watchdog/statusis intentionally open rather than auth-gated. The AC says "auth-gated like the rest of the API" — the comment inmain.tsexplains the deliberate choice (mirroring/agents/health). Fine as-is, but worth a follow-up note in docs or the issue if the design intent diverges from the spec.Added
watchdog-panel.test.tsxcovering all three AC cases: empty state (watchdog-empty), populated state (bothdead-letter-cardandrecovery-card), and Retry click callingpostWatchdogRetry("charles/claude-hooks", 99). All 3 tests pass; full QA clean.Frontend test gap from round 1 is resolved —
watchdog-panel.test.tsxcovers all three AC cases (empty state, populated state, Retry POST). CI green (run #2291, 8m48s).