Limits

Everything this system cannot do, in the same place as everything it can.

An earlier version of this project described capabilities it did not have — simulated telemetry, invented recovery figures, a dashboard with numbers that moved because they were animated rather than measured. This page exists because the claims on the rest of the site are worth nothing without it. If a capability is not listed on Anatomy with the API that provides it, assume it is absent.

The hard boundaries

It cannot stop a denial-of-service attack

A flood arrives at the network before any JavaScript exists to see it. Nothing running in your browser can defend the pipe it was delivered over — that belongs to the CDN in front of the site, and it is not this code. The Proving Ground's flood vector blocks the main thread, which is real main-thread pressure and a genuinely different problem wearing a similar word.

It cannot prevent tampering — only detect and undo it

There is no lock here. Every defence is a response that happens after the change has already landed. For a static page that is enough, because putting the node back is indistinguishable from it never having left. For anything with side effects it would not be.

You can delete the immune system itself

It is JavaScript running in your browser, and your browser obeys you, not this site. Open the console, disconnect the observer, and nothing stops you. What this defends against is the accidental and the injected — a script that got in, an asset that failed, a widget that broke the DOM — not the person holding the machine.

An injected inline script runs before it can be removed

Appending a script executes it synchronously; MutationObserver delivers on a microtask afterwards. Ejection is containment, not prevention. Prevention is the Content-Security-Policy header, which is set at the edge and does its work before any of this code is involved.

The known gaps

A disabled stylesheet is caught late

Setting `sheet.disabled = true` changes a property, and no MutationObserver reports a property assignment. The idle sweep finds it within about two seconds. Until then, the page is genuinely unstyled — you can watch that gap happen on the Proving Ground.

A captured exception is witnessed, not repaired

Errors and unhandled rejections are recorded with their origin. Whatever the throw interrupted stays interrupted. The ledger marks these `observed` rather than `healed`, because calling them healed would be a lie told by a colour.

Two sensors are Chromium-only

`performance.memory` and the `longtask` entry type do not exist in every browser. Where they are missing, the dashboard prints unavailable and the reason. It does not estimate, interpolate, or quietly show a zero.

The record does not survive the tab

The ledger lives in memory and mirrors to sessionStorage. Close the tab and it is gone. Aggregating across visitors would need a server to send it to, and this site deliberately does not have one — so the honest scope of the record is one session.

Draining the queue can drop a simultaneous mutation

`takeRecords()` during a repair discards records the repair itself generated, and can take a genuine change that landed in the same microtask with it. The idle sweep exists to catch what that loses. It is a known gap with a known mitigation, not a solved problem.

With JavaScript off, none of this runs

No sensing, no repair, no ledger. The page still renders and reads correctly, because it is static HTML — and an attacker with scripting disabled has no scripting attack surface either. Worth stating rather than discovering.

What is left

A page that notices when it is damaged, puts itself back, measures how long that took, and keeps a record you can check.

That is a smaller claim than the one this project started with, and it is the one that survives being tested. Go and test it — the Proving Ground hands you the tools, and devtools works just as well.