---
title: "Which Checks Do Sites Fix? 349 Repeat Scans Compared"
slug: repeat-scan-change-study
published: 2026-10-12T03:17:09.523834+00:00
updated: 2026-10-12T03:17:09.523834+00:00
author: "AIScan Content Team"
author_url: https://aiscan.site/about
category: "AI Readiness"
tags: corpus study, scan history, agent readiness, check:C1, check:C2, check:D3, check:B2, check:B1, check:D1
description: "We compared 349 sites scanned 7+ days apart: 34.7% fixed at least one check. See which checks owners fix first, which fixes last and which ones decay."
url: https://aiscan.site/blog/repeat-scan-change-study
---

Most scanner posts tell you what to fix. Fewer tell you what people actually fixed. AIScan keeps every scan it has ever run, and many sites get scanned more than once, so we can answer a plainer question: when a site owner scans, changes something and scans again weeks later, which checks move?

On 12 October 2026 we queried our own production database for hosts with at least two scans seven or more days apart. We found 349 of them. Comparing each host's earliest scan with its latest, 121 (34.7%) passed at least one check they had not passed before. Another 192 (55.0%) gained and lost nothing. The overall score rose by 4.5 points on average, but the median host did not move at all. The more useful result is which checks account for the movement: Markdown negotiation (C1) and llms.txt (C2) lead by a wide margin, the AI bot rules in robots.txt (B2) decay faster than anything else we measured, and the optional Content Signals line (B1) went backwards.

## Quick summary

| Question | Measured answer | Section |
|---|---|---|
| How many repeat-scanned sites improved? | 111 of 349 (31.8%) scored higher, 58 (16.6%) lower, 180 (51.6%) the same | Whole-scan section |
| How many fixed at least one check? | 121 of 349 (34.7%); 85 only gained, 36 gained and lost, 36 only lost | Whole-scan section |
| Which check do owners fix first? | C1 Markdown negotiation: 47 fixes against 3 losses, net +44 | Fixed-first ladder |
| Which fix lasts? | E2 (0 of 24 lost), C2 (3 of 118), C1 (3 of 72) | Stickiness section |
| Which one decays? | B2 lost 25 of 89 passes (28.1%), B1 lost 35 of 60 (58.3%) | Decay section |
| How long until change shows up? | Under 14 days almost nothing (6 of 34 hosts); 14 days or more, about 36% | Time section |
| What should I do? | Fix the file-based checks first, then re-scan after any robots.txt regeneration | Practical section |

**What the data says:** owners fix checks that are a single file or a single response header, and those fixes stay fixed. Policy lines inside robots.txt are the opposite. They get added, then a CMS, plugin or CDN rewrites the file and they disappear. If you only re-scan after you fix something, you will miss the checks that regress.

**Best for a site owner:** start with C1, C2 and D3, then put a re-scan on a schedule so B2 and B1 losses are caught. **For a team running a CI gate:** gate on the checks that rarely regress and only monitor the rest. The [CI gate guide](/blog/aiscan-ci-gate-github-actions) shows the wiring.

## How we measured it

The limits of this data decide how far to trust it, so they come before the results.

We ran every query on 12 October 2026 against production. The population is all site-scope scans stored under rubric version 2026.08.2, the version live since 24 August 2026. A host is the URL with the scheme and any leading `www.` removed. We left out `aiscan.site`, because our own repeated self-scans would skew the numbers upward. Page-scope scans were excluded too, so a deep link scan cannot be mistaken for a homepage re-scan.

Across that population there are 710 hosts, 506 of them scanned at least twice. For each host we took the earliest scan and the latest scan, and kept the host only if the two were at least seven days apart. That left 349 hosts with an average gap of 27.4 days. Scans in between are ignored, so a host that fixed a check and broke it again before its last scan counts as unchanged on that check.

The core shape is a pair of `DISTINCT ON` queries joined on the host, then unnest the check array of each report and match checks by ID:

```sql
WITH s AS (
  SELECT lower(regexp_replace(regexp_replace(url,'^https?://(www\.)?',''),'[/?#].*$','')) AS h,
         created_at, result
  FROM scans
  WHERE rubric_version = '2026.08.2' AND scope = 'site' AND url !~* 'aiscan\.site'
), f AS (SELECT DISTINCT ON (h) h, result r0, created_at t0 FROM s ORDER BY h, created_at ASC),
   l AS (SELECT DISTINCT ON (h) h, result r1, created_at t1 FROM s ORDER BY h, created_at DESC),
   p AS (SELECT f.h, r0, r1 FROM f JOIN l USING (h) WHERE t1 - t0 >= interval '7 days')
SELECT c0->>'id' AS check_id,
       count(*) FILTER (WHERE c0->>'status' <> 'pass' AND c1->>'status' = 'pass') AS fixed,
       count(*) FILTER (WHERE c0->>'status' = 'pass' AND c1->>'status' <> 'pass') AS lost
FROM p
CROSS JOIN LATERAL jsonb_array_elements(r0->'checks') c0
JOIN LATERAL jsonb_array_elements(r1->'checks') c1 ON c1->>'id' = c0->>'id'
GROUP BY 1 ORDER BY 2 DESC;
```

Commerce checks (M1, M3, M4) apply to only 110 of the 349 hosts, and every other check applies to all 349. "Fixed" means any non-pass status (fail, partial or info) became pass. "Lost" is the reverse. Every figure comes from aggregate SQL. We never read individual rows and no host is named here.

Four limits belong here rather than at the end:

1. **The sample is self-selected.** People rescan a site because they care about it, usually right after changing something. These hosts are more engaged than the average site.
2. **We do not know why anything changed.** A pass that appears after three weeks might be a deliberate fix, a platform update, a CDN setting or a new theme. We see the result, not the cause.
3. **Some movement is scanner noise.** Our [determinism self-audit](/blog/aiscan-check-determinism-self-audit) found that 77.6% of back-to-back scan pairs matched and that individual checks flip between 0.6% and 5.3% of the time when the gap is one to 24 hours. We use those rates below as a ceiling on how much of a check's movement could be noise.
4. **The first scan tends to be the worse one.** The same audit found fail-to-pass flips outnumbering pass-to-fail flips by more than two to one. That biases an earliest-versus-latest comparison towards improvement, so read the gains as an upper bound.

## Did the scores move?

Not for most hosts. Half of them ended exactly where they started.

| Outcome (earliest vs latest scan) | Hosts | Share |
|---|---|---|
| Score higher | 111 | 31.8% |
| Score the same | 180 | 51.6% |
| Score lower | 58 | 16.6% |
| Up 10 points or more | 68 | 19.5% |
| Down 10 points or more | 31 | 8.9% |

The mean score went from 50.3 to 54.8, a gain of 4.46 points. The median change is zero. A mean that sits well above its median tells you a minority of hosts made large gains and carried the average. That matches the 68 hosts that rose by ten points or more, against 31 that fell by that much.

Counting check verdicts rather than scores gives a tidier picture. Across the 349 hosts there were 373 fixes (a non-pass check became a pass) and 165 losses, a net gain of 208. That is 1.07 fixes and 0.47 losses per host.

| Pattern across all scored checks | Hosts | Share |
|---|---|---|
| Fixed at least one, lost none | 85 | 24.4% |
| Fixed at least one and lost at least one | 36 | 10.3% |
| Lost at least one, fixed none | 36 | 10.3% |
| No check changed between pass and non-pass | 192 | 55.0% |

The 36 hosts in the third row are the interesting ones. One host in ten got worse without improving anything, and as the next sections show, a large share of those losses sit in two robots.txt checks.

## Fixes come in bundles

Before the per-check view, one more number from the same data. The 373 fixes are not spread evenly. They came from 121 hosts, which is 3.1 fixed checks per host that fixed anything. The 165 losses came from 72 hosts, 2.3 per host that lost anything.

That shape fits how sites actually change. Nobody adds Markdown negotiation alone. A developer sits down with a report, or an agent-readiness checklist, or a plugin that ships three features at once, and several checks flip together. The same goes for losses: a robots.txt rewrite takes B1 and B2 out in one go, and a theme change can drop C3 and E3 together.

It also puts a ceiling on the noise worry. Adding up the half-flip-rate ceilings for every check in the table below gives about 87 of the 373 fixes that scanner noise could in principle produce. That is a generous upper bound, because noise would not produce fixes at the same rate across the board. Even if all of it were noise, at least 286 fixes would remain.

## The fixed-first ladder

Here is every check, ordered by net movement. "Fixed" and "Lost" count hosts. The last column is a rough ceiling on how many of those transitions scanner noise alone could produce in one direction: half the check's one-to-24-hour flip rate from the determinism audit, times 349.

| Check | What it tests | Passing first | Passing latest | Fixed | Lost | Net | Noise ceiling, one way |
|---|---|---|---|---|---|---|---|
| C1 | Markdown content negotiation | 20.6% | 33.2% | 47 | 3 | +44 | about 9 |
| C2 | /llms.txt | 33.8% | 43.6% | 37 | 3 | +34 | about 6 |
| D3 | Link header for discovery | 47.0% | 54.4% | 34 | 8 | +26 | about 8 |
| E2 | Machine-readable API description | 6.9% | 13.5% | 23 | 0 | +23 | about 7 |
| P4 | OAuth discovery | 12.6% | 18.9% | 25 | 3 | +22 | about 4 |
| P1 | API catalog (RFC 9727) | 13.2% | 18.9% | 24 | 4 | +20 | about 8 |
| C3 | Structured HTML | 42.7% | 47.3% | 26 | 10 | +16 | about 7 |
| B2 | Explicit AI bot rules | 25.5% | 28.9% | 37 | 25 | +12 | about 6 |
| E3 | Server-rendered text | 65.9% | 69.1% | 19 | 8 | +11 | about 9 |
| D1 | robots.txt present | 68.8% | 71.3% | 19 | 10 | +9 | about 4 |
| D2 | XML sitemap | 73.4% | 74.8% | 16 | 11 | +5 | about 4 |
| E5 | Content feed (RSS, Atom, JSON Feed) | 25.5% | 26.1% | 11 | 9 | +2 | about 6 |
| P3 | Agent Skills bundle | 9.5% | 10.0% | 6 | 4 | +2 | about 1 |
| E4 | Canonical host and HTTPS | 60.2% | 60.5% | 15 | 14 | +1 | about 2 |
| P2 | MCP Server Card | 2.9% | 3.2% | 2 | 1 | +1 | about 2 |
| E1 | Correct 404 handling | 73.6% | 73.1% | 13 | 15 | -2 | about 2 |
| B1 | Content Signals (optional) | 17.2% | 10.9% | 13 | 35 | -22 | about 2 |

B3 had 8 passing hosts at both scans and no transitions. The commerce checks, on 110 hosts, moved little: M4 gained 6 and lost 1, M1 lost 1, M3 never passed. The [commerce checks reference](/docs/checks/commerce) explains why those three behave differently from the rest.

Three things stand out.

**The two heaviest content checks lead.** C1 is weighted 8 and C2 is weighted 6 in the [content checks reference](/docs/checks/content), the two highest weights in that dimension. They are also the two where the ladder is least ambiguous: C1 gained 44 net against a noise ceiling of about 9, and C2 gained 34 against about 6. Whatever else is going on, these are not flips.

**The capability checks moved more than their starting rates suggest.** E2, P4 and P1 started under 14% and each added about six percentage points. In plain terms, a host that adds a well-known file for one of these checks is rare, but when it happens it sticks. E2, the API description check, had no losses at all.

**Some rows are inside the noise.** E4, E1, P2, P3 and E5 moved by two points or fewer, and their ceilings are about the same size as their net. We would not read anything into them. The same goes for D2: five net on a ceiling of about four.

### Conversion rate: how often a failing host fixed it

Absolute counts favour checks that many hosts fail. A fairer view asks, of the hosts that did not pass a check at their first scan, how many passed it at their last?

| Check | Hosts not passing at first scan | Fixed | Conversion |
|---|---|---|---|
| D3 | 185 | 34 | 18.4% |
| D1 | 109 | 19 | 17.4% |
| D2 | 93 | 16 | 17.2% |
| C1 | 277 | 47 | 17.0% |
| C2 | 231 | 37 | 16.0% |
| E3 | 119 | 19 | 16.0% |
| B2 | 260 | 37 | 14.2% |
| E1 | 92 | 13 | 14.1% |
| C3 | 200 | 26 | 13.0% |
| E4 | 139 | 15 | 10.8% |
| P4 | 305 | 25 | 8.2% |
| P1 | 303 | 24 | 7.9% |
| E2 | 325 | 23 | 7.1% |
| B1 | 289 | 13 | 4.5% |
| E5 | 260 | 11 | 4.2% |
| P3 | 316 | 6 | 1.9% |
| P2 | 339 | 2 | 0.6% |

Now the ladder has three clear rungs.

- **Rung one, roughly 14% to 18%:** D3, D1, D2, C1, C2, E3 and B2. These are things a site owner can do in an afternoon: a header, a robots.txt, a sitemap, a Markdown route, a text file. About one failing host in six did them.
- **Rung two, 4% to 11%:** E4, P4, P1, E2, B1 and E5. They need either a platform setting (canonical host and HTTPS), a feed, an API description, or a protocol most owners have not heard of yet.
- **Rung three, under 2%:** P3 and P2. The MCP Server Card and the Agent Skills bundle need something to point at, an MCP server or a skill set, so they move only when a team has built one. Nobody adds a server card on its own.

If you are deciding where to start, the ladder is a reasonable map of what peers actually got done. It says nothing about what is most valuable. For that, the [highest-impact fix study](/blog/agent-readiness-highest-impact-fix) measures the per-check score gap directly.

### A worked example

Take a site that fails C1, C2 and D3 and nothing else on this list. Using the documented weights (C1 is 8, C2 is 6, D3 is 3) those three checks carry 17 weight points between them. They are also the three where a typical failing host in our data had the best odds of getting a pass, 17.0%, 16.0% and 18.4%. A team with an afternoon and a short backlog can make a real dent with these three. A team that starts with P2, the MCP Server Card, is working on the check where 2 of 339 failing hosts managed a fix in a month.

That does not make P2 a bad idea. If you run an MCP server, publishing the card is correct, and our [MCP server card guide](/blog/publish-mcp-server-card) explains how. It only means the data shows where peers spent their effort, and the effort went to the cheap file and header checks first.

## Some fixes stay fixed

A fix only counts if it survives the next deploy. Here is the other side of the ledger: of the hosts passing each check at their first scan, how many no longer passed at the last?

| Check | Passing at first scan | Lost by last scan | Loss rate |
|---|---|---|---|
| E2 | 24 | 0 | 0.0% |
| C2 | 118 | 3 | 2.5% |
| C1 | 72 | 3 | 4.2% |
| D1 | 240 | 10 | 4.2% |
| P4 | 44 | 3 | 6.8% |
| E4 | 210 | 14 | 6.7% |
| P1 | 46 | 4 | 8.7% |
| D2 | 256 | 11 | 4.3% |
| E1 | 257 | 15 | 5.8% |
| E3 | 230 | 8 | 3.5% |
| C3 | 149 | 10 | 6.7% |
| D3 | 164 | 8 | 4.9% |
| B2 | 89 | 25 | 28.1% |
| B1 | 60 | 35 | 58.3% |

Most checks lose between 0% and 9% of their passes over four weeks, a figure close to what the determinism audit would predict from noise alone. File-based checks do best: a file, once published, sits there. E2 lost nothing, C2 lost 2.5%, C1 lost 4.2%.

Then there are the two outliers.

## The decay: B2 and B1

B2 looks for explicit `User-agent:` blocks naming the known AI crawlers. Of 89 hosts that passed it at their first scan, 25 (28.1%) did not at their last. B1 looks for a `Content-Signal` line in robots.txt. Of 60 hosts that had one, 35 (58.3%) no longer did. B1 is the only check in the table with a clear fall in its pass rate: 17.2% down to 10.9%. E1 slipped by half a point, which is inside the noise.

What do the stored results say about why? Every one of the 35 B1 losses carries the same evidence string, "not declared (optional / emerging standard)". Every one of the 25 B2 losses reads "0 known AI agent(s) addressed in robots.txt". So the file was read and held no such lines. We then looked at the D1 result for those same 25 hosts on the latest scan. Twenty-one of them returned a robots.txt with a 200 status. Only four were an HTTP error. This is not mostly a case of the scanner being refused. The robots.txt that answered no longer named the bots.

We cannot see the earlier or later file contents, only the verdict, so what follows is inference. The pattern fits a robots.txt that something else rewrote. A WordPress SEO plugin regenerates the file when settings are saved or the plugin is swapped. A CDN dashboard can inject or drop managed rules. A static site rebuilds the file from a template that never had the lines. Any of those would add the AI rules for a while and then lose them, with nobody editing the file by hand.

This is why we keep making the case for one tool owning the file on WordPress. [ThinkRank](https://thinkrank.ai) manages robots.txt, robots meta, schema and llms.txt from one plugin, so there is a single place where the AI bot rules live, and it imports settings from Rank Math, Yoast, AIOSEO and SEOPress. Three plugins writing to one robots.txt is how a rule gets overwritten without anyone choosing to remove it. Yoast, Rank Math and AIOSEO each edit the file too, and each is a fine choice as long as only one of them is editing. If you are building the file by hand instead, our [robots.txt starter for AI crawlers](/blog/robots-txt-starter-for-ai-crawlers) is a complete template to start from.

One caution on B1. It is informational and cannot lower your score, per the [bot access checks reference](/docs/checks/bot-access), and the Content-Signal convention is still a proposal. A fall in B1 passes does not mean owners are rejecting the idea. It means a line that nobody is required to keep was easy to lose.

## Does time matter?

Yes, and mostly in the first two weeks.

| Gap between first and last scan | Hosts | Mean score change | Fixed at least one check | Up 10 or more | Down 10 or more |
|---|---|---|---|---|---|
| 7 to 13 days | 34 | +1.09 | 6 (17.6%) | 5 | 2 |
| 14 to 29 days | 141 | +5.60 | 50 (35.5%) | 31 | 12 |
| 30 days or more | 174 | +4.20 | 65 (37.4%) | 32 | 17 |

With a one-week gap, a host is barely different. The 34 hosts in that bucket gained about one point, and only six fixed anything. After two weeks the share fixing at least one check doubles, to roughly 36%, and it stays near there. The 30-day bucket does not do better than the 14-to-29-day bucket. It has more losses (17 hosts down ten or more, against 12), which is consistent with fixes eroding while new ones accumulate more slowly.

The practical reading: if you scan, change something and scan again a few days later, you are measuring your change only if your change was instant. Many changes are not. A CDN rule can take hours to propagate, and a static site has to rebuild. Give it a day, scan twice, and treat a check that disagrees across the two scans as a finding in itself, as the determinism audit recommends.

## What the data cannot say

- **It cannot say the scanner caused the fix.** We have no way to tell whether someone read an AIScan report and acted, or ran into the same standards elsewhere.
- **It cannot separate a rate limit from a regression with certainty.** We saw that most B2 losses had a readable robots.txt, but for the other checks a 429 or a CDN challenge on the latest scan can look like a loss. The determinism audit traced 12 of 18 D1 flips to a 429, and the same effect applies here. Our [link header corpus](/blog/link-header-discovery-corpus) and [well-known files census](/blog/well-known-agent-files-corpus) carry the same caveat.
- **It cannot see after the last scan.** A host that fixed a check the day after its last scan looks unchanged.
- **It says nothing about hosts that never rescan.** Of the 710 hosts, 204 were scanned once and roughly 157 more were rescanned only inside the first week. They are not in the 349.
- **It does not measure value.** A fixed check means the file or header now exists and parses. It does not mean any agent used it. For adoption at large, the [state of AI agent readiness](/blog/state-of-ai-agent-readiness-2026) is the baseline.

## What to do with this

The ladder gives a sensible order for a first pass, and the decay gives you a reason to re-scan.

1. **Scan once and note the failing checks.** Run `npx aiscan-cli yoursite.com` or paste your address into the box at [aiscan.site](https://aiscan.site/); both are free with no account. Look at C1, C2, D3 and B2 first.
2. **Fix the file and header checks.** Add `/llms.txt` for [C2](/docs/checks/content), serve Markdown on `Accept: text/markdown` for C1, and add a `Link` header for [D3](/docs/checks/discoverability). If you would rather verify by hand, `curl -sI -H "Accept: text/markdown" https://yoursite.com/` shows the C1 content type and `curl -sI https://yoursite.com/` shows any `Link` header.
3. **Add the AI bot rules to robots.txt, then protect them.** Put the explicit `User-agent:` blocks in place for [B2](/docs/checks/bot-access). On WordPress, let one plugin own the file. [ThinkRank](https://thinkrank.ai) is built for that. If you use Rank Math, Yoast or AIOSEO, check that only one of them has robots.txt editing switched on.
4. **Re-scan after every robots.txt regeneration.** Plugin updates, theme changes, CDN rule changes and site rebuilds are the moments B2 and B1 vanish. Put the scan on a schedule, which is what [monitoring over time](/blog/monitor-ai-readiness-over-time) is for.
5. **Skip rung three until you have something to point at.** P2 and P3 only make sense after you run an MCP server or ship skills.

## Run it on your own site

Scan your site at [aiscan.site](https://aiscan.site/) or with `npx aiscan-cli yoursite.com`, then compare against this table. The relevant checks are C1 and C2 (content), D1, D2 and D3 (discoverability), B1 and B2 (bot access), and P1, P4 and E2 (capabilities). Browse the full set of [guides](/guides) to find the fix for each, and scan again in two weeks.

