Anastatica — Self-Healing Web Performance Runtime
Agent-native web performance, diagnosed and healed in the browser — with SLSA-verified provenance on every fix.
1. Why your use case is a strong fit for WebMCP
WebMCP runs inside the active user session, in the browser's own JavaScript process, with direct access to the live document. Anastatica uses that in-process execution to close the gap between runtime telemetry detection and DOM remediation: the agent reads real
PerformanceObserverdata and applies a fix to the very page it is observing, with no server round trip and no reload. That makes the agent an active co-pilot for the runtime itself rather than an isolated external chatbot describing a problem it cannot touch.
2. How it creates a better user experience
Instead of enduring dropped frames and input latency climbing into the hundreds of milliseconds, the user gets an evidence-gated repair with no reload or lost form state. In the recorded Chromium run the legacy filter blocked for about 470 ms; after the reversible containment patch activated bounded animation-frame batches, its input handler returned in about 1 ms.
3. What people and agents can do together that was impossible before
A person keeps working inside a heavy, unvirtualized data interface while an autonomous agent continuously inspects W3C Long Animation Frame telemetry, bounds layout thrashing through CSS Containment, and hashes the resulting DOM into an in-toto SLSA v1.2-shaped statement for every mutation it makes. The human keeps the interaction; the agent takes over the performance work and leaves behind a tamper-evident audit trail of exactly what it changed, when, and under whose authority.
4. Briefly explain how you implemented WebMCP
A top-level TypeScript bootstrap registers seven typed tools exactly once with awaited
document.modelContext.registerToolcalls. EachinputSchemais a real JSON object generated from its Safe Rust DTO throughschemars. Tool execution lazily loads the zero-unsafeRust/WASM engine and dispatches into its in-memory gateway. The engine isolates LoAF, INP and CLS statistics, returns token-bounded diagnoses, refuses to mutate without matching evidence, and journals every applied patch for rollback.
Inspiration
Modern web performance is broken in a way classic tooling cannot fix.
A single unlucky CSS selector can cascade into a 500-millisecond layout reflow that locks the main thread, tanks Interaction to Next Paint, and drives users away. Traditional profilers tell you that you are slow. They rarely tell you what to do about it, and they never fix it for you.
Meanwhile a new capability is arriving in the browser: in-browser AI agents that can read and act on a page through the open W3C WebMCP standard. If a page could expose its performance telemetry to an agent as tools, and the agent could act on that telemetry as a diagnostician, we could finally close the loop — from symptom, to diagnosis, to surgical remediation, to a verifiable audit trail.
Anastatica is that loop.
What it does
A zero-panic WebAssembly build in the browser watches real rendering telemetry
via PerformanceObserver, exposes it to an in-browser AI agent through WebMCP
(document.modelContext), and lets that agent apply real CSS containment after
a local fail-closed selector check. The optional server applies authoritative
Biscuit Datalog verification when a statement is submitted; the static demo
hashes the changed DOM state with BLAKE3 and does not claim a digital signature.
End to end:
- A user drops 50,000 unvirtualized rows onto the page. Frame rate collapses and INP spikes into the red.
- Through
document.modelContext, the agent invokesinspect_rendering_bottlenecks. The microkernel compiles an anomaly report, packs the top offenders into a strict 1024-token budget, and hands back a dense, prioritized report pinpointing#catalog-gridas the uncontained culprit subtree. - The agent calls
auto_heal_pipeline. Matching telemetry authorizes the operation, the local allow-list and geometry pre-flight run, andcontain: layout paint; content-visibility: autois applied. - The microkernel seals the mutation with a two-tier hash (XXH3 dirty-check + BLAKE3 digest) and emits an in-toto SLSA v1.2 provenance statement, which the overlay's Provenance panel renders — subject, digest before and after, patch id, and the capability policy that permitted it.
The entire diagnostic-and-heal loop runs locally in the browser. No server compute is required to heal the page.
It is not a demo with a runtime attached
Anastatica ships as an in-page DevTools overlay that injects itself into a
shadow root and binds to nothing on the host page. One <script src> — or a
bookmarklet — puts it on any site, the way DevTools works.
That is a load-bearing claim, so it is demonstrated rather than asserted: the
overlay has been driven on an unrelated third-party page (a bookshop with a
serif typeface, * { box-sizing: content-box } and its own button styling),
where it auto-detected the heaviest subtree, measured live INP and frame rate,
and was unaffected by the host's CSS in either direction. The demo portal
itself now contains zero Anastatica hooks — a test fails if any reappear.
Six panels, each over real tool output. Three of them are the first user interface those subsystems have ever had:
| Panel | What it shows |
|---|---|
| Vitals | LCP / INP / CLS / FPS, live, with sparklines |
| Network | The critical path ranked from Resource Timing, plus the Link: preload set a server would emit as a real 103 Early Hints |
| Hydration | Server/client attribute drift against the SSR baseline — read-only until you ask it to repair |
| Runtime | Anomalies carrying the z-score the CUSUM detector computed, plus contain / roll back / auto-heal |
| Tools | The seven WebMCP tools, their effect annotations, and whether an agent host is connected |
| Provenance | The SLSA statement, digests, and the LocalGuard capability policy |
What it will not do. Observation works anywhere. Mutation is gated:
LocalGuard grants contain and hydrate only on an explicit allow-list and
refuses #login-form, #payment-details and #checkout-form outright. On a
page the grants were not written for the mutating tools are refused, and the
Provenance panel states that on screen. A performance tool has no business
rewriting a checkout form, and the policy was not loosened to make the demo
smoother.
How we built it
A Rust edition 2024 workspace of nine crates plus a host application, bound by one non-negotiable contract: 100% Safe Rust.
anastatica-protocol— SLSA v1.2 schemas, in-toto statement models, JSON-RPC 2.0 types.anastatica-adapter— an anti-corruption layer (reached via theana::alias), 24 rows isolating every third-party crate behind plainana::adapter::<module>::<fn>free functions that need no trait import, plus a real, injection-tested Biscuit Datalog capability policy.anastatica-api— the runtime trait, DTOs, and the WebMCP tool catalog (single source of truth for every advertised schema).anastatica-telemetry— streaming Welford statistics, a 2-sided CUSUM change-point detector, a deterministic token budgeter, and a real server-side OpenTelemetry SDK with an OTLP/HTTP exporter and W3Ctraceparentpropagation.anastatica-core— realPerformanceObservertelemetry, real DOM remediation, the headless engine, and the realdocument.modelContextbridge.anastatica-ui— a zero-VDOM Rust/WASM runtime that constructs no DOM. It attaches to a host page it does not own, binds that page's controls to real WebMCP tool calls, and writes live Core Web Vitals into readouts the page provides.anastatica-storage— a 4-tier engine:quick_cache+ TTL'd Moka (L1), Redb (L2), XXH3-checksummed Fjall journal (L3), and an L4DistributedTierreplicating to a peer node (TiKV behind an off-by-default feature).anastatica-server— Axum + jsonrpsee with Tower middleware andtower_http::tracerequest spans, emitting real103 Early Hintson HTTP/1.1 and HTTP/2, cleartext or TLS.
Challenges
Zero-unsafe, zero-panic, zero-indexing. #![forbid(unsafe_code)] across the
workspace, with clippy::pedantic + clippy::nursery denied and dozens of
additional lints forbidden outright — no unwrap, no expect, no panic!, no
slice indexing, no raw as casts, no integer division. Every fallible path
returns a Result and uses checked arithmetic. This is a compiler-enforced
contract, not a style preference, and it applied to the integration tests too.
A Datalog injection we found in our own code. The first capability-policy
draft built its Datalog source with format!(), string-concatenating the
untrusted selector. A hostile selector could break out of the string literal and
inject a permissive policy. We proved it with a failing test, then fixed it with
AuthorizerBuilder::code_with_params, binding untrusted values as typed Datalog
terms. The regression test is still in the suite.
WASM microkernel compilation. Building a zero-panic microkernel for
wasm32-unknown-unknown while keeping the same crates usable from the server
required careful feature-gating and clean boundaries.
Accomplishments we're proud of
- A closed loop built from real pieces, verified by a real build — real
PerformanceObservertelemetry, evidence-gated DOM containment, a local fail-closed capability gate, and a production Vite bundle produced end-to-end by our build script. - 100% Safe Rust with zero panics across the whole workspace, compiler-enforced.
- Sub-microsecond anomaly detection — streaming Welford/CUSUM fed by real telemetry.
- SLSA v1.2 provenance of real state with a two-tier XXH3 + BLAKE3 hash computed from the real post-mutation DOM.
- A 595-test suite — 503 Rust, 59 Vitest in jsdom, 33 Playwright in Chromium — all passing under strict forbidden-lint rules, including single-registration, evidence-gating, metric-isolation, raw HTTP/2 frame, peer replication, Datalog injection, and corrupted-journal tests.
What's next
- Native HTTP/3 (QUIC) — in-process
quinn+h3, once upstreamh3(currently 0.0.8) reaches v1.0. HTTP/3 is terminated at the edge today. - TiKV L4 backend against a live cluster — the code compiles behind the
distributedfeature but has never been exercised against a real deployment, so it stays gated. - INP attribution across browsers —
long-animation-frameandlayout-shiftare Chromium-only, so LoAF telemetry is inactive on Firefox and Safari.
Accuracy notes — corrections applied to the draft answers
Four claims in the original draft were not supported by the shipped code and were corrected rather than submitted as-is:
- "SLSA v1.0" → "SLSA v1.2". The codebase, README, ADR-0007 and every
emitted statement use v1.2 (
https://slsa.dev/spec/v1.2). - "embedded
tiktoken-rsBPE token budgeting" → removed.tiktoken-rssits behind the adapter'sserverfeature and is not in the WASM dependency graph. The browser budgets with the Tier-1ApproxCountercharacter-entropy estimator, which never undercounts;TokenBudgeteris generic overTokenizerConcept, so the tier is a type parameter rather than a hard-coded call (ADR-0015). Exact BPE is reachable as a server RPC. The 1024-token ceiling and Z-score ranking are real; the BPE vocabulary in the browser is not. - "broken SSR hydration" → reinstated. This note previously said
repair_hydration_boundarywas unimplemented future work. It ships, and it is Phase 2 of the demo: the portal's timestamp is re-rendered in the browser's local timezone,data-tzdrifts from the server's recorded baseline, and the Export action silently stops binding. The tool compares the live DOM againstdata-anastatica-ssrand restores it with no reload. What it does not do is revive framework event closures — see ADR-0009. - "1-RTT" → "within a single agent turn". The healing loop is entirely in-browser and performs no network round trip at all, so "1-RTT" understates it and invites a question we'd have to walk back.
One further note for the demo, corrected 2026-09-03: this previously said
the catalog registers exactly four tools and that there is no
auto_heal_pipeline. Both are now out of date — the catalog registers seven,
and auto_heal_pipeline is one of them, closing diagnose → contain → attest in a
single call. The fallback control is the HUD's Repair now button (the
"⚡ Simulate Agent Action" button went with the console it belonged to, ADR-0017);
it dispatches that same registered tool, so a judge without a WebMCP host runs
exactly what an agent would.
Built With
- axum
- blake3
- brotli
- chatgpt
- chrome
- cloudflare
- core-web-vitals
- fjall
- local-first
- moka
- openai
- opentelemetry
- redb
- rust
- slsa
- tikv
- tokio
- typescript
- vite
- web-components
- webassembly
- webmcp
- xxh3
- zero-trust
- zstd
Log in or sign up for Devpost to join the conversation.