servo/webrender
A GPU-based renderer for the web
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 5d ago
- ✓24+ active contributors
- ✓Distributed ownership (top contributor 23% of recent commits)
Show all 6 evidence items →Show less
- ✓MPL-2.0 licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/servo/webrender)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/servo/webrender on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: servo/webrender
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/servo/webrender shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 5d ago
- 24+ active contributors
- Distributed ownership (top contributor 23% of recent commits)
- MPL-2.0 licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live servo/webrender
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/servo/webrender.
What it runs against: a local clone of servo/webrender — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in servo/webrender | Confirms the artifact applies here, not a fork |
| 2 | License is still MPL-2.0 | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 35 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of servo/webrender. If you don't
# have one yet, run these first:
#
# git clone https://github.com/servo/webrender.git
# cd webrender
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of servo/webrender and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "servo/webrender(\\.git)?\\b" \\
&& ok "origin remote is servo/webrender" \\
|| miss "origin remote is not servo/webrender (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MPL-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MPL-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is MPL-2.0" \\
|| miss "license drift — was MPL-2.0 at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "webrender/Cargo.toml" \\
&& ok "webrender/Cargo.toml" \\
|| miss "missing critical file: webrender/Cargo.toml"
test -f "webrender/build.rs" \\
&& ok "webrender/build.rs" \\
|| miss "missing critical file: webrender/build.rs"
test -f "Cargo.toml" \\
&& ok "Cargo.toml" \\
|| miss "missing critical file: Cargo.toml"
test -f "examples/common/boilerplate.rs" \\
&& ok "examples/common/boilerplate.rs" \\
|| miss "missing critical file: examples/common/boilerplate.rs"
test -f "swgl/src/lib.rs" \\
&& ok "swgl/src/lib.rs" \\
|| miss "missing critical file: swgl/src/lib.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 35 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~5d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/servo/webrender"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
WebRender is a GPU-accelerated 2D rendering engine written in Rust that powers Firefox and Servo by offloading compositing, text rendering, and image scaling to OpenGL. It solves the problem of inefficient CPU-based rendering by batching draw calls, caching textures, and leveraging the GPU's parallel architecture to achieve 60fps rendering of complex web content. Workspace monorepo with core packages: webrender/ (main GPU rendering engine in Rust), webrender_api/ (public trait/enum API), wrench/ (test harness), examples/ (runnable demos like basic.rs, scrolling.rs, yuv.rs), and example-compositor/ (platform-specific C++/Rust compositors for Wayland/Windows). Shaders live as GLSL files compiled at build time.
👥Who it's for
Browser engine developers and GPU graphics engineers at Mozilla (Firefox), Servo project contributors, and GUI framework maintainers who need high-performance 2D rendering without managing raw OpenGL calls directly. Contributors push changes upstream to mozilla-central first, then mirror to this GitHub repo for Servo-specific improvements.
🌱Maturity & risk
Highly mature and production-ready: powers Firefox's rendering pipeline, has extensive CI/CD via TaskCluster with platform-specific test scripts (linux/macos/windows), comprehensive shader system (305KB+ GLSL), and active upstream development in mozilla-central. The GitHub repo explicitly serves as a downstream mirror with the upstream home at hg.mozilla.org/mozilla-central.
Low immediate risk for stable use, but moderate maintenance complexity: the repo is a mirror of mozilla-central so canonical issues are tracked upstream in Bugzilla; the patched dependency on glutin (custom 'wr' branch for Android) creates version coupling; shader modifications require careful validation across platforms due to font rendering differences and OSMesa testing constraints. Single-threaded upstream (mozilla-central) can delay Servo-specific fixes.
Active areas of work
Active upstream synchronization via .github/workflows/sync-upstream.yml to pull changes from mozilla-central; example-compositor contains recent work on Wayland and Windows compositing integrations; workspace includes experimental texture cache stress testing and YUV rendering examples. Glean telemetry integration is pinned to version 61.0.0, suggesting ongoing instrumentation work.
🚀Get running
git clone https://github.com/servo/webrender.git
cd webrender
cargo build --release
cargo run --example basic
For full test suite: ci-scripts/linux-debug-tests.sh (requires OSMesa and dev font libraries). To use with Servo, patch Servo's Cargo.toml as documented in README.md.
Daily commands:
Dev build: cargo build in repo root (builds all workspace members). Run example: cargo run --example basic. Run tests: cargo test --release or platform-specific ci-scripts/linux-release-tests.sh. Benchmark: cargo run --example alpha_perf --release. With Servo: add [patch] block to Servo's Cargo.toml pointing to local webrender paths (see README.md).
🗺️Map of the codebase
webrender/Cargo.toml— Workspace root and primary crate manifest defining WebRender's dependencies, features, and build configuration for the GPU rendering enginewebrender/build.rs— Build script that compiles GLSL shaders to C++ and handles platform-specific GPU code generation—essential for understanding shader compilation pipelineCargo.toml— Workspace root defining all member crates (webrender, webrender_api, wrench, examples) and patched dependencies like custom glutin for Androidexamples/common/boilerplate.rs— Reference implementation showing how to initialize WebRender, create windows, and handle the render loop—primary entry point for understanding the APIswgl/src/lib.rs— Software GL implementation fallback renderer written in Rust, critical for platforms without native GPU supportpeek-poke/src/lib.rs— Serialization/deserialization library used internally for efficient data marshalling between CPU and GPU memoryglsl-to-cxx/src/lib.rs— GLSL-to-C++ transpiler that converts shader code; core to the shader compilation pipeline in build.rs
🛠️How to make changes
Add a New Rendering Feature (e.g., new blend mode)
- Define the feature type in webrender_api using serializable Rust structs with PeekPoke derives (
webrender_api) - Implement GPU command generation logic in webrender/src (frame builder adds commands to batch) (
webrender/Cargo.toml) - Write or modify GLSL shaders in webrender/res or inline shader strings; they'll be compiled by build.rs (
webrender/build.rs) - Add software renderer equivalent in swgl (blend.h for blend modes, rasterize.h for rasterization logic) (
swgl/src/blend.h) - Create test example in examples/ demonstrating the new feature with boilerplate setup (
examples/basic.rs)
Add Support for a New Platform or Compositor
- Create new compositor module in example-compositor/compositor-<platform>/ with Cargo.toml and build.rs for FFI bindings (
example-compositor/compositor-windows/Cargo.toml) - Implement platform-specific window creation and event loop in src/lib.rs (C++ via lib.cpp for system APIs) (
example-compositor/compositor-windows/src/lib.rs) - Update workspace Cargo.toml to include new platform crate and add any platform-specific glutin patches (
Cargo.toml) - Add CI script in ci-scripts/ (e.g., ci-scripts/platform-name-tests.sh) following existing pattern (
ci-scripts/linux-debug-tests.sh)
Optimize Shader Performance or Add GPU Feature
- Write or modify GLSL shader source; build.rs will automatically transpile via glsl-to-cxx during compilation (
webrender/build.rs) - For complex transformations, modify the GLSL→C++ pipeline in glsl-to-cxx/src/lib.rs or hir.rs (
glsl-to-cxx/src/lib.rs) - Create example in examples/ to benchmark performance and validate correctness (
examples/alpha_perf.rs) - Run wrench test suite to ensure no regressions across all platforms (
wrench)
Add a Fallback Software Rendering Path
- Implement rasterization logic in swgl/src/rasterize.h following SIMD patterns for batch processing (
swgl/src/rasterize.h) - Update swgl/src/lib.rs to export the new rendering function and integrate into GL abstraction (
swgl/src/lib.rs) - Add peek-poke serialization support if new data structures are introduced (peek-poke-derive macro) (
peek-poke/peek-poke-derive/src/lib.rs) - Write integration test in swgl to verify fallback path produces correct output (
swgl/Cargo.toml)
🔧Why these technologies
- Rust — Memory safety without garbage collection; performance-critical rendering code benefits from zero-cost abstractions and SIMD vectorization
- OpenGL API — Cross-platform GPU abstraction; used by Firefox, Servo, and many GUI frameworks; well-established for 2D rendering
- GLSL Shaders — Standard GPU shading language; glsl-to-cxx transpiler allows compilation to C++ for platforms without native GPU support
- peek-poke Serialization — Zero-copy binary serialization enables efficient transfer of display lists and uniform data from CPU to GPU
- Software Rasterizer (swgl) — Fallback renderer for headless environments, testing, and platforms lacking GPU drivers; pure Rust ensures portability
⚖️Trade-offs already made
-
GPU-first design with software fallback
- Why: Maximizes performance on modern hardware while maintaining portability and testability on non-GPU systems
- Consequence: Must maintain two separate rendering paths; complexity in keeping CPU and GPU implementations in sync
-
GLSL shaders transpiled to C++ rather than using platform-native GPU APIs (Metal, Vulkan, DX12)
- Why: Single codebase across Windows, macOS, Linux; leverages stable OpenGL ecosystem used by upstream Gecko
- Consequence: Cannot access cutting-edge GPU features; performance limited by OpenGL capabilities; shader compilation adds build time
-
Upstream home in mozilla-central with GitHub as downstream mirror
- Why: Maintains alignment with Firefox's rendering pipeline; accepts improvements via Bugzilla and Gecko contribution workflow
- Consequence: Repository branching and sync overhead; contributions may require dual submission (GitHub and mozilla-central)
-
Separate webrender_api crate for public types
- Why: Stable versioning boundary; allows end-users to depend on serializable types without pulling entire renderer
- Consequence: API contract must be strictly maintained; breaking changes require major version bumps
🪤Traps & gotchas
OSMesa requirement: Text rendering tests are sensitive to system font libraries (Fedora example noted in README); CI uses OSMesa for headless consistency but differences still occur. Upstream-first workflow: changes should go to Bugzilla/mozilla-central first; PRs here may be rejected if not aligned. Glutin patching: custom patched glutin from jamienicol/glutin 'wr' branch required for Android; upgrading will break builds. Shader compilation: GLSL files are embedded and compiled at build time; shader bugs only surface after full recompile. Platform compositor coupling: example-compositor has separate C++ bindings per platform (Wayland, Windows); changes need validation on multiple platforms. Glean telemetry: pinned to exact version 61.0.0; version mismatches with Firefox can cause subtle incompatibilities.
🏗️Architecture
💡Concepts to learn
- Retained-Mode Scene Graph — WebRender's DisplayList captures a frame's draw commands once and reuses them across frames; understanding this (vs immediate-mode) is critical for optimizing render passes and avoiding redundant recompilation
- GPU Texture Atlasing & Cache Eviction — WebRender packs multiple images/glyphs into single GPU textures to reduce draw calls; the cache eviction policy directly impacts frame time and memory footprint, making this essential for performance tuning
- Deferred Rendering & Quad Batching — WebRender batches draw calls by texture and blend mode into quads before submitting to GPU; this reduces OpenGL API overhead and is the core optimization enabling 60fps rendering of complex pages
- OSMesa (Off-Screen Mesa) — WebRender's test suite uses OSMesa for headless GPU rendering on CI; it ensures consistent reference image comparisons across platforms but introduces font rendering quirks requiring platform-specific test adjustments
- GLSL Shader Compilation at Build Time — Shaders are embedded as static strings and compiled to GPU bytecode during cargo build; modifications require full recompilation, and shader bugs only surface at runtime, making debugging harder than CPU code
- Transform Stack & Nested Compositing — WebRender maintains a stack of affine transforms for nested iframes and elements; correctly managing this stack is critical for hit testing, clipping, and scrolling behavior in complex layouts
- GPU Frame Pipelining & Vsync Synchronization — WebRender queues frames asynchronously with the GPU while respecting vsync; understanding frame latency, backpressure, and swap chains is essential for tuning responsiveness on different displays
🔗Related repos
servo/servo— Consumes WebRender as primary rendering backend; uses [patch] block in Cargo.toml to integrate local modificationsgfx-rs/gfx— Alternative GPU abstraction layer; WebRender could theoretically support gfx instead of direct OpenGL (explored in earlier versions)mozilla/gecko-dev— Upstream repository (hg.mozilla.org); WebRender in gfx/wr folder is canonical source; GitHub repo syncs from hereemilk/egui— Immediate-mode 2D UI renderer for Rust; contrasts with WebRender's retained-mode approach for web contentxi-editor/druid— Retained-mode GUI framework using piet (composable graphics); shares architectural patterns with WebRender's scene graph
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add CI workflow for WebRender examples validation
The repo contains 8+ examples (alpha_perf.rs, animation.rs, basic.rs, blob.rs, document.rs, iframe.rs, image_resize.rs, multiwindow.rs, scrolling.rs, texture_cache_stress.rs, yuv.rs) but there's no dedicated CI workflow to ensure they compile and run correctly. Currently only .taskcluster.yml exists. Adding a GitHub Actions workflow would catch example breakage early and ensure the examples directory remains a reliable entry point for contributors.
- [ ] Create .github/workflows/examples-validation.yml to run 'cargo build --example <name>' for each example in examples/
- [ ] Test on at least Linux and macOS (following pattern from ci-scripts/linux--tests.sh and ci-scripts/macos--tests.sh)
- [ ] Verify the workflow doesn't conflict with existing .taskcluster.yml by documenting both in ci-scripts/README.md if it doesn't exist
Add integration tests for example-compositor modules
The example-compositor directory contains three platform-specific implementations (compositor, compositor-wayland, compositor-windows) with C++/Rust FFI (build.rs, lib.cpp, lib.rs files), but there are no visible tests validating their behavior. This is high-risk code since it bridges unsafe FFI boundaries and has platform-specific implementations.
- [ ] Create example-compositor/tests/ directory with integration tests for basic compositor functionality (e.g., window creation, frame submission)
- [ ] Add platform-conditional tests in example-compositor/tests/integration.rs using #[cfg(target_os = "...")] for wayland/windows-specific codepaths
- [ ] Update example-compositor/Cargo.toml to include dev-dependencies for testing (e.g., tempfile, test fixtures)
Document the Firefox upstream sync workflow in .github/sync/
The repo contains sync infrastructure (.github/sync/sync.sh, .github/sync/webrender.paths, .github/workflows/sync-upstream.yml) designed to pull changes from mozilla-central, but there's no documentation explaining how contributors should handle upstream patches, conflicts, or the sync-back process. The README mentions 'improvements should be submitted upstream in Gecko' but doesn't explain the mechanism. This creates friction for contributors unfamiliar with the dual-repo model.
- [ ] Create .github/sync/README.md documenting the upstream sync process, when/how to use sync.sh, and what webrender.paths controls
- [ ] Add guidance on whether contributors should: (a) submit PRs here first then upstream, or (b) go directly to Gecko, with examples for each case
- [ ] Reference the sync-upstream.yml workflow and explain what happens when sync-upstream action runs (e.g., frequency, conflict resolution)
🌿Good first issues
- Add shader documentation comments to GLSL source files in the shader directories—no GLSL files have module-level docs explaining their purpose (quad rendering vs. text vs. image), blocking newcomer understanding of the rendering pipeline
- Create a minimal example demonstrating frame timing and latency measurement (examples/timing.rs) using webrender's profiler APIs—currently alpha_perf.rs benchmarks but examples lack latency instrumentation visible to contributors
- Add integration tests for
webrender_api/src/display_list.rsthat validate DisplayList serialization round-trips and transform stack correctness—currently only exercised indirectly through wrench reference tests
⭐Top contributors
Click to expand
Top contributors
- @nical — 23 commits
- [@Glenn Watson](https://github.com/Glenn Watson) — 15 commits
- @web-flow — 13 commits
- @jamienicol — 6 commits
- @bradwerth — 5 commits
📝Recent commits
Click to expand
Recent commits
e1c924e— Update the sync location to reflect the new Firefox repository (mrobinson)c4bd5b4— Sync only to theupstreambranch and do not cherry-pick (mrobinson)bd7704a— Syncing to upstream (816766e1a236fcb7eebaa493e492b55c419ada05) (web-flow)52f1bf2— Bug 1893956 - Ensure consistent rounding for draw compositor tile and clip rects. r=gfx-reviewers,nical (jamienicol)71c6434— Bug 1893956 - Disallow underlay compositor surfaces during low-quality pinch zoom. r=gfx-reviewers,nical (jamienicol)2915d85— Backed out changeset 9b9f5e47c9b0 (bug 1917493) for causing build bustages. CLOSED TREE (smolnar-sheriff)e63e790— Bug 1917493 - Enable quad box shadows on a subset of outset box-shadows r=gfx-reviewers,nical (Glenn Watson)1ffff3a— Bug 1911542 - Recycle a vector in ResourceCache::begin_frame. r=gfx-reviewers,lsalzman (nical)669db3d— Bug 1912019 - Work around serde(skip). r=gfx-reviewers,lsalzman,ErichDonGubler (nical)53907eb— Bug 1912019 - Don't use malloc_size_of for the render task graph. r=gfx-reviewers,lsalzman (nical)
🔒Security observations
The WebRender codebase demonstrates reasonable security practices overall, being a Mozilla-affiliated GPU rendering engine written in memory-safe Rust. However, several medium-risk issues exist: the use of a custom patched dependency fork for glutin bypasses standard security audits, exact version pinning on glean prevents automatic security updates, and the 'panic = abort' configuration across all profiles could enable DoS attacks. CI/CD scripts and Docker configurations require additional review. The codebase lacks evidence of hardcoded secrets or injection vulnerabilities typical of web services, which is appropriate for a graphics library. Recommendations focus on dependency management, error handling configuration, and CI/CD script security hardening.
- High · Patched Dependency with Custom Fork —
Cargo.toml - [patch.crates-io] section. The Cargo.toml uses a patched version of 'glutin' pointing to a custom GitHub fork (jamienicol/glutin branch 'wr') instead of the official crates.io version. This bypasses standard dependency verification and security audits, potentially introducing unreviewed code changes. Fix: Verify the fork is maintained by a trusted maintainer, ensure the fork is kept in sync with upstream security patches, and consider upstreaming the Android-specific changes to the official glutin project. Document why the fork is necessary. - Medium · Pinned Glean Dependency Version —
Cargo.toml - [workspace.dependencies] section. The workspace dependency 'glean' is pinned to an exact version (=61.0.0), which prevents automatic security patch updates. If a vulnerability is discovered in glean 61.0.0, it will not be automatically fixed by dependency management. Fix: Use a compatible version constraint (e.g., '~61.0' or '^61.0') to allow patch updates, or establish a regular dependency audit process to check for security updates and update the pinned version regularly. - Medium · Panic Behavior in Production (abort) —
Cargo.toml - [profile.release] and [profile.dev] sections. Both dev and release profiles are configured with 'panic = abort', which causes the entire process to terminate on panic. This could be exploited for denial-of-service attacks if panic conditions can be triggered by malicious input. Fix: Consider using 'panic = unwind' in release builds to allow graceful error handling, or ensure robust input validation and error handling to prevent panics from untrusted data sources. - Low · CI/CD Script Security —
ci-scripts/ directory (sync.sh, linux-debug-tests.sh, etc.). Shell scripts in ci-scripts/ directory (particularly sync.sh and test scripts) may contain unvalidated inputs or unsafe command execution patterns. Shell scripts are often targets for injection attacks. Fix: Review all shell scripts for: proper input validation, use of quotes around variables, avoidance of eval, use of 'set -e' and 'set -u' flags, and secure handling of credentials. Consider migrating critical CI/CD logic to Rust or well-tested CI platforms. - Low · Docker Build Configuration —
ci-scripts/docker-image/Dockerfile. The Dockerfile in ci-scripts/docker-image/ was not provided for analysis, but Docker build files can introduce security issues through outdated base images, missing security updates, or overly permissive configurations. Fix: Ensure: base image is from official sources and regularly updated, all packages are pinned to specific versions, multi-stage builds are used to minimize final image size, and non-root user is configured. Run container image scanning tools (e.g., Trivy, Snyk). - Low · GitHub Workflow Security —
.github/workflows/sync-upstream.yml. The sync-upstream.yml workflow may execute external code or scripts without proper security controls, particularly around the sync process from mozilla-central. Fix: Review workflow permissions, use specific action versions (not 'latest'), ensure secrets are properly scoped, validate external data before use, and implement code review requirements before merging synced content.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.