# The coverage dashboard Explains what `README.md`'s coverage table means, how `docs/feature-map.json` decides it, and how to keep both in sync after a change. ## The five statuses Every browser-compat-data leaf key under `css`, `html`, `api`, `javascript`, `svg`, `webassembly`, `http` and `mathml` gets exactly one of: - **generated** — implemented by an admitted model-written candidate under `crates/layout/src/generated/`. Each generated function's `.provenance.json` names the spec section it was generated against; `docs/feature-map.json`'s rule for the key points at the function's source file. - **hand-written** — implemented by substrate code the project wrote by hand: box tree construction, the DOM/cascade boundary onto Stylo, and the reflection/tree-mutation work in `crates/dom`. - **linked** — implemented by a real dependency the project integrates rather than writes, using `docs/platform-areas.md`'s own word for it: Stylo for CSS cascade and computed values today, and a JavaScript engine once one is chosen and actually wired in. It covers only the feature surface the dependency itself computes. The project's glue and adapter code around the dependency — the DOM/cascade boundary in `crates/dom/src/style.rs`, the reads in `crates/dom/src/computed.rs` — is hand-written, and a key whose behavior beyond the cascaded value (layout, box generation) is done by this project's own code keeps that code's status: `display` and `position` are hand-written, `width` and the `top`/`right`/`bottom`/`left` offsets are generated, even though Stylo computes their values. The `linked` rules today are the remaining properties of the style subset compared against `getComputedStyle` (`docs/dump-format.md`), which `docs/platform-areas.md` → "Style, layout and rendering" reports as fully matched. Properties Stylo cascades but that no comparison checks stay unreached until one does, and `javascript.*` stays unreached while no JavaScript engine exists. - **oracle only** — not implemented, but a three-engine-comparable probe or conformance suite exists for it (`docs/oracle-coverage.md`, `docs/conformance-oracles.md`). - **unreached** — none of the above: no rule in `docs/feature-map.json` matches the key. This is the default, and today it accounts for most of the surface — see "Expect small numbers" below. ## The rule map `docs/feature-map.json` is the one hand-maintained input: an ordered array of rules, for example: ```json { "pattern": "css.properties.width", "status": "generated", "evidence": "crates/layout/src/generated/width.rs" } ``` - `pattern` is a browser-compat-data key or a prefix of one, dot-separated (`css.properties.width` matches that key and everything nested under it, such as `css.properties.width.calc`). A segment can be `*` (matches any one segment) or end in `*` (matches a segment starting with that text — `api.GPU*` matches `api.GPUAdapter`, `api.GPUDevice`, and so on). - Rules are checked in file order; the first match wins. A key no rule matches is `unreached`. - `evidence` must resolve to something real: a repo-relative file path, `path/to/doc.md#Heading Text` naming an actual heading in that file, or `corpus/-triage.json#` naming a feature triage record in which every page tagged for that key passes (`docs/web-features-map.md` → "The status rule"). `oracle/suites/dashboard.mjs` checks every rule's evidence on every run and refuses to compute anything if one doesn't resolve. ## Updating the table ```mermaid flowchart LR map["docs/feature-map.json
(hand-edited rules)"] --> dash["dashboard.mjs --render"] bcd["browser-compat-data"] --> dash dash --> json["docs/dashboard.json"] dash --> hist["docs/dashboard-history.json"] hist --> svg["docs/dashboard-history.svg"] dash --> svg dash --> readme["README.md table
and graph"] json --> test["readme_dashboard.rs
and --check"] hist --> test svg --> test readme --> test ``` 1. Edit `docs/feature-map.json` — add, remove or repoint a rule, and commit it with the work it describes. This is the only step a spec does by hand. 2. Landing does the rest. After every merge, `bench/after-land.sh` runs `bench/dashboard-update.sh` in the primary checkout. It checks whether `docs/dashboard.json`, `docs/dashboard-history.json`, `docs/dashboard-history.svg` and the tables in `README.md` still match a fresh computation (`node oracle/suites/dashboard.mjs --check`; a different `date` alone does not count), and if not runs `node oracle/suites/dashboard.mjs --render` and commits the files that changed as `dashboard: regenerate at ` on the base branch. Numbers that did not move add no commit. The computation is offline and takes seconds. It refuses, and writes nothing, when any of the four files has uncommitted changes; on any failure it puts them back and the landing's output line names it as not done (`web-features map or dashboard not updated`), and the next landing tries again because it recomputes from scratch. 3. To refresh by hand (a track that wants the numbers before landing, or after a failed landing step), run `npm run dashboard` from `oracle/` (equivalent to `node suites/dashboard.mjs --render` from that directory, or `node oracle/suites/dashboard.mjs --render` from the repo root) and commit the four generated files together, even when the history did not gain an entry, because the SVG and the README block are rewritten from it on every `--render`. `crates/harness/tests/readme_dashboard.rs` fails `cargo test --workspace` if the README table, the JSON, the history and the graph disagree with each other, and `node oracle/suites/dashboard.mjs --check` fails if any of them is stale against a fresh computation from browser-compat-data. `bench/dashboard-update-test.sh` covers the landing step: numbers moved gives one commit, numbers unchanged gives none, and an uncommitted change in one of the four files is refused. ## The history graph `README.md` carries a small graph above the table, between `` and ``. It is a committed file, `docs/dashboard-history.svg`, embedded with ``: GitHub's README sanitizer strips inline ``, `