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 PerformanceObserver data 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.registerTool calls. Each inputSchema is a real JSON object generated from its Safe Rust DTO through schemars. Tool execution lazily loads the zero-unsafe Rust/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:

  1. A user drops 50,000 unvirtualized rows onto the page. Frame rate collapses and INP spikes into the red.
  2. Through document.modelContext, the agent invokes inspect_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-grid as the uncontained culprit subtree.
  3. The agent calls auto_heal_pipeline. Matching telemetry authorizes the operation, the local allow-list and geometry pre-flight run, and contain: layout paint; content-visibility: auto is applied.
  4. 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 the ana:: alias), 24 rows isolating every third-party crate behind plain ana::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 W3C traceparent propagation.
  • anastatica-core — real PerformanceObserver telemetry, real DOM remediation, the headless engine, and the real document.modelContext bridge.
  • 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 L4 DistributedTier replicating to a peer node (TiKV behind an off-by-default feature).
  • anastatica-server — Axum + jsonrpsee with Tower middleware and tower_http::trace request spans, emitting real 103 Early Hints on 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 PerformanceObserver telemetry, 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 upstream h3 (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 distributed feature but has never been exercised against a real deployment, so it stays gated.
  • INP attribution across browsers — long-animation-frame and layout-shift are 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:

  1. "SLSA v1.0" → "SLSA v1.2". The codebase, README, ADR-0007 and every emitted statement use v1.2 (https://slsa.dev/spec/v1.2).
  2. "embedded tiktoken-rs BPE token budgeting" → removed. tiktoken-rs sits behind the adapter's server feature and is not in the WASM dependency graph. The browser budgets with the Tier-1 ApproxCounter character-entropy estimator, which never undercounts; TokenBudgeter is generic over TokenizerConcept, 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.
  3. "broken SSR hydration" → reinstated. This note previously said repair_hydration_boundary was 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-tz drifts from the server's recorded baseline, and the Export action silently stops binding. The tool compares the live DOM against data-anastatica-ssr and restores it with no reload. What it does not do is revive framework event closures — see ADR-0009.
  4. "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
Share this project:

Updates

Submission history