Project Info
This project did not submit a demo video on Devpost.
Inspiration
Every team ships two kinds of bugs: The kind that throws (crashes, 500s, timeouts) The kind that's silently wrong (a total that's off, money leaking on every order) Your tests pass, and your app is still broken. These bugs hide for months until a customer or a finance report finds them for you. That's the gap nobody's watching, so we built Canary to watch it.
What it does
Canary is a self-healing correctness agent β an agent that catches the bug, root-causes it, fixes it, writes the regression test, proves the fix works, and remembers it, with zero humans in the loop. It runs on two oracles: Sentry watches what throws (errors, 500s, traces) and gives the agent the trace context to reason over. Impact: instant root-cause instead of hours digging through logs. The Computer Use Agent is an agent in a real cloud browser that takes action and watches what's silently wrong. Impact: catches the revenue-leaking bugs your tests and error monitoring both miss. In our demo, Canary caught a checkout charging $26 for two $52 seats (a 50% revenue leak every unit test passed right over) and a silent 54% drop in average order value, then fixed both with no human in the loop. Together they power one agentic, memory-backed loop: detect, fix, verify, remember.
How we built it
TypeScript end to end. A Next.js app is both the seeded checkout and the live dashboard. Claude (Anthropic) is the brain for exploration, triage, and fix synthesis. The explorer drives a real Browserbase cloud browser over CDP, with a synthetic in-page cursor so every click shows up in the live view and the replay. The Sentry SDK supplies trace correlation, unified fingerprinting, breadcrumb reasoning trails, and the resolved-to-regressed lifecycle. Redis backs the knowledge base. Every external dependency sits behind an interface with a fake implementation, so 226 tests and CI run fully offline and live integrations switch on only when their keys are present.
Challenges we ran into
Browserbase only records the context it hands you. Spin up a fresh one and the replay is blank, so we drive the recorded page directly. Dev-mode hot reload cannot upgrade through a tunnel, so we serve a production build and run all checkout traffic from inside the cloud page. The Sentry and Browserbase SDKs fought over Node globals until we registered the Browserbase shim first. We refused to label a fix "verified" unless a real verifier actually ran the test, which closed the gap between looking done and being done. A naive threshold detector either misses the drop or cries wolf, so median and MAD plus a drop gate plus a post-resolve cooldown made it fire once, on the real thing.
Accomplishments we're proud of
A genuinely autonomous loop, no human click, that detects, fixes, verifies, and remembers. Honesty as a feature: verified means a test ran, backed by 226 deterministic offline tests. Every sponsor is load-bearing, not bolted on. Anthropic is the brain, Sentry is the oracle and memory, Browserbase is the body, Redis is the long-term memory. A test suite that grows itself, because every bug found writes the assertion nobody wrote.
What we learned
Catching silent bugs needs an oracle that declares intent, not one that waits for a crash. Robust statistics matter: median and MAD survive the outliers that sink mean and standard deviation. And observability is strongest as a substrate an agent reasons over, not a dashboard you check after the fact. Sentry is not where bugs die β it is the agent's brain.
What's next
Point it at any app and auto-derive invariants instead of seeding them. Open each fix as a real pull request, feeding Sentry's Seer instead of fighting it. A long-horizon miner over accumulated Sentry history that surfaces extreme outliers no single run hits. More oracle types: accessibility, performance budgets, and data-integrity checks. Built With: typescript, next.js, anthropic, claude, sentry, browserbase, redis, playwright, vitest, node.js, react
Bloodhound πβπ¦Ί
Dual-oracle autonomous QA swarm β finds the silent bugs your tests and your error monitoring miss.
Bloodhound explores a real app through a headless browser like a chaos-user and catches failures with two oracles:
- Sentry catches what throws β crashes, errors, slow spans.
- A browser agent catches what's silently wrong β logic/UI bugs where nothing throws (e.g. the cart shows $10 for two $10 items). It declares what it expects before acting, then flags observed β expected.
Everything logs into Sentry, our history DB. When something breaks, a triage agent pulls the correlated Sentry trace (browser = symptom, Sentry = cause), root-causes it, fixes the code, and writes a regression test so it can never recur.
Built for the UC Berkeley AI Hackathon 2026. Shared context lives in the sibling team-brain repo (
../team-brain).
This repo
The Bloodhound codebase. Three workstreams build against one set of frozen contracts:
| Area | Owner | Path |
|---|---|---|
| Triage & fix engine + frozen contracts | Vikash | src/contracts/, src/triage/, src/sentry/, src/cache/ |
| Browser explorer + demo app | Shashank | (incoming) |
| Dashboard + memory/persistence + wiring | Prajit | (incoming) |
The contracts (src/contracts/)
The two hand-off shapes that keep three people building one project β mirrors
team-brain reference/api-contracts.md:
Findingβ detection β triage. What was expected, what was observed, how to reproduce, and the SentrytraceIdto correlate.Resolutionβ triage β dashboard. Confirmed?, root cause, fix diff, regression-test path, verified?, status.signature(finding)/SeenStoreβ stable dedup over detection-time fields only (neverrootCauseβ that would be circular), so triage skips duplicates.
Sample fixtures for teammates to build against live in fixtures/.
Develop
npm ci
npm run typecheck
npm test
Anything touching Anthropic or Sentry is dependency-injected behind an interface
with a Fake* implementation, so the suite runs fully offline. Live
implementations activate only when the relevant API keys are present in the
environment.
Analysis
View
Metric
- 48
- 40
- 14
- 11
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- CSSIn code
- Next.jsIn code
- ReactIn code
- RedisIn code
- Tailwind CSSIn code
- TypeScriptIn code
- AnthropicClaimed
- Node.jsClaimed
6 of 8 appear in the indexed code. 2 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
- Claude CodeConfig Β· Commits
- CodexConfig
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
902 KB
Source files
148
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
vikashftw/Canary
176 files Β· 1.4 MB Β· @ 07f0d1a
Structure
Interface
40 files Β· 23%Screens, components and styles rendered to the user.
API & routing
16 files Β· 9%Request entry points: routes, handlers and controllers.
Application logic
57 files Β· 32%Domain rules, services and shared utilities.
+5 more
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here β open the file browser to check anything the diagram implies.
Languages
- TypeScript95%
- Markdown3%
- Shell2%
- CSS0%
- YAML0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
web/package.json
npm Β· 13- @sentry/nextjs
- next
- react
- react-dom
- redis
- +8 more
explorer/package.json
npm Β· 5- @browserbasehq/sdk
- @browserbasehq/stagehand
- @sentry/node
- playwright
- tsx
package.json
npm Β· 5- redis
- +4 more
Declared in the repositoryβs manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
Feature verification
Automatic regression test generationVerified
Canary writes the regression test for the bug it fixes, so a test suite grows itself
Claimed on Devposthigh confidencesrc/triage/regression.ts:1β generateRegressionTest(finding, rootCause, llm) called from engine.resolveRegressionTestsrc/triage/engine.ts:131β engine pairs every resolved fix with a regression test, cached fallback if live generation fails
Browser agent silent-bug oracle (expected vs observed)Verified
A browser agent in a real cloud browser declares what it expects, then flags observed != expected to catch silent logic bugs
Claimed on readmehigh confidenceexplorer/run.ts:95β explicit expectedTotal (oracle) vs observedTotal (cart.total) fields, with violated: expectedTotal !== observedTotalexplorer/run.ts:393β human-readable expected/observed strings built from the invariant check and used in the finding
Browserbase cloud browser via CDPVerified
The explorer drives a real Browserbase cloud browser over CDP
Claimed on Devposthigh confidenceexplorer/browser.ts:1β Browserbase session setup referencedexplorer/stagehand-run.ts:1β Stagehand-driven run against Browserbase, matches Built-With listing
Demo bug: checkout charges $26 for two $52 seats (50% revenue leak)Verified
Canary caught a checkout charging $26 for two $52 seats, a 50% revenue leak every unit test passed right over
Claimed on Devposthigh confidenceweb/src/app/api/checkout/_cart.ts:139β comment describes exact bug: sums each line's unit price once regardless of qty, and worked example gives computed_total=26 vs sum_line_totals=52web/src/app/api/checkout/bug/route.ts:1β runtime toggle to enable/disable the seeded bug for the demo
Dependency-injected external services with Fake* offline implementations (226 tests, offline CI)Verified
Every external dependency sits behind an interface with a fake implementation, so 226 tests and CI run fully offline
Claimed on Devposthigh confidencesrc/triage/verifier.ts:49β FakeVerifier offline stand-in alongside live CommandVerifier, env-gated via createVerifiertests/memory-fakes.test.ts:1β tests exercise Fake* memory/redis implementationstestsβ grep across tests/ counted exactly 226 it()/test() call sites, matching the claimed number
Frozen shared contracts (Finding/Resolution/signature/SeenStore)Verified
Finding and Resolution are the two hand-off shapes; signature/SeenStore give stable dedup over detection-time fields
Claimed on readmehigh confidencesrc/contracts/finding.ts:1β Finding contract definitionsrc/contracts/resolution.ts:1β Resolution contract definitionsrc/contracts/signature.ts:1β signature() dedup function, used by triage engine's seen-store check
Next.js app is both the seeded checkout and the live dashboardVerified
A Next.js app is both the seeded checkout and the live dashboard
Claimed on Devposthigh confidenceweb/src/app/checkout/page.tsx:1β seeded checkout UIweb/src/app/page.tsx:1β dashboard entry point in the same Next.js app
Redis-backed knowledge base / memory of past bugsVerified
Redis backs the knowledge base; every bug found writes the assertion nobody wrote and Canary remembers it
Claimed on Devposthigh confidencesrc/memory/redis-client.ts:24β RedisLike interface wraps node-redis for sAdd/sIsMember/hSet, used by SeenStore and vector indexsrc/memory/finding-store.ts:8β findings captured with fingerprint:[signature] for dedup/history in Sentry+memorysrc/memory/similar-findings.ts:1β similar-findings lookup backing the 'remembers it' claim
Robust statistical anomaly detector (median/MAD, drop gate, cooldown) for silent AOV dropsVerified
Median and MAD plus a drop gate plus a post-resolve cooldown made the detector fire once, on the real thing
Claimed on Devposthigh confidenceweb/src/lib/detector.ts:91β detectAnomaly implements rolling median baseline, MAD spread, robust z-score, and a %-drop gate exactly as claimedweb/src/lib/autonomy-runner.ts:1β references cooldown handling around detector firing
Sentry oracle for crashes/errors/tracesVerified
Sentry watches what throws (errors, 500s, traces) and gives the agent trace context to reason over
Claimed on Devposthigh confidencesrc/sentry/trace-client.ts:15β TraceClient.getTrace fetches Sentry event-trace data by traceId, mapped via mapSentryTraceResponsesrc/triage/engine.ts:62β triage() pulls the Sentry trace for a finding via deps.traceClient before judging/fixing
Sentry trace correlation, unified fingerprinting, and resolved-to-regressed lifecycleVerified
The Sentry SDK supplies trace correlation, unified fingerprinting, breadcrumb reasoning trails, and the resolved-to-regressed lifecycle
Claimed on Devposthigh confidencesrc/memory/finding-store.ts:306β captures events with fingerprint: [s] (signature) for unified groupingweb/src/lib/memory-timeline.ts:10β comment + logic describe re-firing the same fingerprint to flip a resolved Sentry issue to regressedexplorer/sentry-breadcrumbs.ts:1β breadcrumb reasoning trail emission for the explorer's actions
Synthetic in-page cursor for live view/replayVerified
A synthetic in-page cursor so every click shows up in the live view and the replay
Claimed on Devposthigh confidenceexplorer/cursor.ts:1β Injects a DOM cursor via page.evaluate, explicitly designed to be captured in both the live CDP screencast and the recorded replay
Triage agent: root cause + fix synthesis via Claude/AnthropicVerified
Claude is the brain for triage and fix synthesis; a triage agent root-causes and fixes the code
Claimed on readmehigh confidencesrc/triage/engine.ts:64β judge() call uses an injected LLMClient to confirm/root-cause the findingsrc/triage/fixer.ts:1β LiveLLMFixStrategy produces a fixDiff via the LLM, with cached-canonical fallback
Verification: a real verifier runs the regression test before marking 'verified'Verified
We refused to label a fix verified unless a real verifier actually ran the test
Claimed on Devposthigh confidencesrc/triage/verifier.ts:120β CommandVerifier actually spawns the test command (e.g. npx playwright test) and reads exit code 0 as passsrc/triage/engine.ts:178β Resolution.verified stays false unless deps.verifier is invoked and returns true
Sentry Seer hand-off strategyCode-supported
Feeding Sentry's Seer instead of fighting it (opening each fix as a PR is listed as future work, but a Seer hand-off strategy exists now)
Claimed on Devpostmedium confidencesrc/triage/seer.ts:36β SeerHandoffStrategy hands a confirmed bug + regression test to Seer instead of patching, but is explicitly opt-in and never in the engine's default fix-strategy chain
Zero-human autonomous loop (detect, fix, verify, remember)Code-supported
A genuinely autonomous loop, no human click, that detects, fixes, verifies, and remembers
Claimed on Devpostmedium confidencesrc/triage/engine.ts:56β engine chains judge -> fix -> regression test -> verify -> finalize without human input in-processweb/src/lib/autonomy-runner.ts:1β an autonomy-runner orchestrates the loop for the dashboard, but full 'zero human in the loop' end-to-end (explorer -> webhook -> triage -> verify -> memory) spanning processes could not be fully traced in this triage
Auto-deriving invariants for any app (instead of seeded ones)Claimed only
Point it at any app and auto-derive invariants instead of seeding them
Claimed on Devposthigh confidenceAuto-opening a real pull request for each fixClaimed only
Open each fix as a real pull request, feeding Sentry's Seer instead of fighting it
Claimed on Devposthigh confidence
An AI agent derived these features from the projectβs Devpost page and readme, then searched the code for each one. Verified features are backed by cited code; claimed-only features had no supporting code, which is not by itself proof a feature is missing.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.