17,886 / 17,886historical scores re-derived exactly
0.000mean drift, time-dependent signals
35,534transitions in the tape — 1,538 published
7,835 / 7,835ledger records reproduced byte-identically

The question everyone is asking about AI-skill scanners this summer is “can they be trusted?” Trail of Bits built malicious skills that walked past five scanners — under an hour each for three of the four. A measurement study ran seven scanners over the same skills and found they agreed on 0.12% of what they flagged. And in Part 1 of this series we showed our own scanner had blocked 13% of the MCP ecosystem — and almost none of it was dangerous.

So we think “can scanners be trusted?” is the wrong question. Any single scan is a floor, not a verdict — we’ve said that since June. The better question, for anyone publishing trust scores, is narrower and harsher:

If someone re-ran your math on your own stored data, would they get your own answer?

A score you can’t replay is an opinion with a number attached. So we tried to break ours.

The test, and the rule we set before running it

MCPSkills keeps a version archive: every tracked MCP server, skill, and package is observed on a roughly 17-hour cycle — currently 2,631 packages, more than 218,000 consecutive observation pairs across 75 days, with zero calendar days missing. Each observation stores the signals we measured, the score they produced, and the algorithm version that produced it.

In late July we audited that archive the way an acquirer’s diligence team would: six independent measurements, each one re-verified by a second, independent pass at full population — no sampling on the numbers that mattered. And we set the kill rule before measuring: if historical scores failed to reproduce materially, everything else stopped.

Result one: 17,886 of 17,886

We re-derived every historical score that carried its stored inputs — 17,886 records — using one rule: compute as of the timestamp the record itself stores.

The case that worried us most

One package’s tier appeared to flicker between scans — the kind of thing that looks like nondeterminism and kills trust in a scoring system. The archive explained it in four stored fields: the algorithm version changed while the package’s version, git tree hash, and manifest hash all stayed identical. A labeled methodology change, not a coin flip. That is what a ledger is for.

Result two: the embarrassing one

This series exists because we publish our failures with the same precision as our wins. Part 1’s failure was over-blocking. Part 2’s failure is stranger: we had been underreporting change — against our own interest.

The same audit counted every version, score, and tier transition present in the raw tape: about 35,500 across the full corpus. Our published change ledger held 1,538.

Not because the data was missing — because our publishing rules were too conservative. Two of them were deliberate signal floors we stand behind (tiny score wobbles don’t deserve a feed entry; a GitHub commit hash changing isn’t a “release”). But two were policy mistakes. The biggest: when our engine changed and re-tiered part of the corpus, we suppressed those records entirely, on the theory that engine news isn’t project news. The theory was half right — engine re-tiers don’t belong in your “what changed this week” feed — but suppressing them made the record incomplete. A complete ledger should store everything and label it, and let each surface filter for its audience.

So that’s what we shipped:

The public feed still shows only subject changes. Your “what changed” page should never be flooded by our engine’s opinions about itself. But the ledger underneath is now complete, labeled, and — the part we care about — checkable.

What this does not prove

Honesty about limits is the point of this series, so:

Replay is not independent re-scoring. These results prove our history is internally consistent — our stored signals plus our versioned algorithm reproduce our published scores. They do not let a third party re-score our history under a different model, because for most of the archive’s life we stored conclusions, not raw evidence. That changed on 2026-07-26: observations now capture the raw upstream responses (OpenSSF Scorecard, OSV, EPSS, KEV), content hashes for what the scanner saw, and contributor snapshots. The evidence archive begins on that date, and we won’t pretend it starts earlier.
The tape is young. Seventy-five days of high-fidelity history. We think a young ledger you can replay beats an old one you have to take on faith, but we’re not going to imply years of depth we don’t have.
A replayable ledger doesn’t make the scores right. It makes them auditable. Part 1 is the proof those are different things: our scores were reproducible the whole time they were also over-blocking. Reproducibility is the property that let us find and fix that publicly.

Why this matters beyond us

The ecosystem is converging on the same lesson from three directions: scanners can be bypassed, scanners disagree, and scanners over-flag. The response can’t be “trust our scanner more.” OWASP’s new Agentic Skills Top 10 points the right way — its first entry asks registries to display publisher trust level and scan status in the UI. We’d add one word to that prescription: display trust signals you can audit. A number on a page is only as good as the record behind it, and the record is only as good as your ability to replay it.

That’s the standard we’re holding ourselves to, in public, with our misses documented in this series. The changes feed is live, the current-scores dataset is CC BY 4.0, the methodology is documented, and if you re-run our math on our data and get a different answer, we want to hear about it — that’s not a threat to the system, it’s the system working.

Check a server before you install it

Run the behavior-based trust report for any MCP server or skill — scored by an engine whose history you can replay.

Open Scanner