|
|
Donner 0.5.1
Embeddable browser-grade SVG2 engine
|
Donner ships a roster of domain-expert subagents that live under .claude/agents/. Each one is a Markdown file with a YAML frontmatter block (name, description) followed by a prompt that gives the agent its voice, its source-of-truth pointers, and its handoff rules.
When you work on Donner with an agent-capable tool (Claude Code, Codex, or any client that understands the .claude/agents/ convention), these files are loaded automatically and made available as delegate targets. Instead of asking one generic assistant every question, you can route a question to the bot that owns the relevant area — BazelBot for a BUILD.bazel change, TextBot for a HarfBuzz shaping bug, TinySkiaBot for a pixel diff in the default backend, and so on.
This page is the map: what each bot owns, when to call it, and how they hand work off to each other.
A mid-size C++ project like Donner has enough distinct sub-disciplines (build, rendering, parsing, text, CSS, security, spec conformance, perf, release) that a single "generalist" agent tends to give shallow answers outside its comfort zone. The roster solves that by:
See AGENTS.md for the repo-wide coding and workflow rules that every agent inherits.
| Agent | Area | When to call |
|---|---|---|
| BazelBot | Bazel build system, custom rules, feature flags, banned-patterns lint, CMake mirror | Adding a target, debugging a *_lint failure, understanding a --config= flag, CMake-mirror questions |
| CSSBot | donner::css parser, selectors, cascade, PropertyRegistry, StyleSystem | Selector parsing bugs, specificity/inheritance questions, how presentation attributes interact with CSS in SVG2 |
| DesignReviewBot | Design docs under docs/design_docs/ | Before a design moves from draft to implementing; periodic scope-drift checks during implementation |
| DuckBot | Big-picture brainstorming, Donner's innovation registry | You're stuck on what to build, not how — architectural reframes, "is there a cleverer way?" |
| GeodeBot | Geode GPU backend (WebGPU/Dawn, Slug, WGSL), RendererGeode, --config=geode | Geode architecture questions, enable_geode gating, adding or editing shaders |
| MiscBot | Cross-cutting refactors, multi-PR initiatives | Planning a background project, breaking work into reviewable chunks; delegates to domain bots for depth |
| ParserBot | donner::xml, donner::svg::parser, donner::css::parser, fuzzer discipline, diagnostics | Parser bugs, fuzzer crashes, error-message quality, designing a new parser |
| PerfBot | Frame-budget discipline, profiling, allocation/hot-path analysis | Perf regressions, animation smoothness, "is this fast enough for 60/120fps?" |
| ReadabilityBot | Modern C++20 readability and safety review | Code review focused on idioms, modern C++, catching antipatterns, template discipline |
| ReleaseBot | Release checklist, versioning, RELEASE_NOTES.md, BCR publishing, build report | What's left before cutting a release, BCR publish flow, build-report issues |
| SecurityBot | Trust boundaries, input validation, fuzzing, resource limits, SVG-engine threat model | Security reviews, adversarial-input crash triage, DoS analysis, safe-input guarantees |
| SpecBot | SVG2 + dependent web standards (CSS, DOM, XML, Filter Effects, Unicode) | Edge-case spec questions, identifying UB, checking what browsers/resvg/librsvg/batik actually do |
| TestBot | GTest/GMock, diagnosable failures, custom matchers | Test-file reviews, "this failure message is useless" problems, promoting assertions into matchers |
| TextBot | Text rendering across the no-text default plus --config=text and --config=text-full | Any text bug, font matching, @font-face, WOFF2, shaping, cross-tier mismatches |
| TinySkiaBot | Vendored tiny-skia-cpp + RendererTinySkia (the default backend) | Pixel diffs in the default backend, SIMD parity, stroke/dash edge cases |
Each agent file in .claude/agents/ starts with the same YAML frontmatter shape:
The description field is what's surfaced to the calling tool's router, so it doubles as the "when to use me" hint.
The exact invocation depends on the client:
You don't need an agent-aware client to benefit from this roster, either. The handoff map below is just as useful as a contributor cheat sheet for "who on the team (or which docs) should I go read before touching area X".
The single most important thing each agent prompt does is name the files it should read first, before speculating. For example, BazelBot's source of truth includes:
If a bot ever gives you an answer that contradicts the code, your first move is to re-point it at its source-of-truth list ("grep first, speculate never") and ask again. A contradictory answer usually means the bot hallucinated rather than that the file has moved.
Agents cooperate. Every bot's prompt ends with a short list of questions it does not own, each paired with the bot that does. A few representative edges:
The handoff rules are intentionally terse in each bot's file — they're meant to be read quickly and routed on. If you find yourself routing a question through three bots, that's usually a sign the work itself should be split.
Every file in .claude/agents/ follows roughly the same shape:
If you want to see a representative example, open .claude/agents/BazelBot.md. The longer-form bots (TextBot, SecurityBot, PerfBot) follow the same structure but with more worked examples.
If a new subsystem gets big enough to deserve its own bot — or an existing bot is getting too broad — follow the pattern:
Removing or renaming a bot works in reverse: grep the other bot files for any outgoing handoff to the old name and update them in the same PR.
See the repo-wide AGENTS.md for the coding, workflow, and review conventions every bot inherits.