v0.0.182
Released Nov 14, 2026
Release Notes
The JSON report now says, for every rule, whether it ran and what it covered (schema 1.20), and squirrel report --diff uses that to count a finding as fixed only when the rule actually looked again: a finding that is gone because its rule was skipped, timed out or never saw the page is listed as not compared instead. A broken link in a site's header, navigation or footer is now its own site-wide check, reported once with the number of pages it is on. Published reports carry a page map so the hosted service can list a report's pages, and cloud credit top-ups go up to $5,000 with bonus credits above $100.
Added
- The JSON report says, for every rule that has a check, whether it ran and what it covered (#1747, #1741 part 2): a top-level
ruleslist of{ ruleId, status, scope, reason? }(JSON schema 1.20).statusisran(a clean pass counts),skippedortimed_out.scopeis{ origin }for a site rule and{ pages }for a page rule: the number of audited pages less the pages its skipped checks name,0when it did not run.reasonis the skip reason of a rule that did not run: a code such astargeted-runwhen the rule gives one, otherwise its skip message. No existing field changed (executedRulesstays as it was). A report re-rendered from a JSON file withreport --inputhas noruleslist. The rule docs pages of the rules that declare their check names (#1741) gain a generated Check names by outcome table, and the JSON format docs describe how to decide "fixed" from two reports. squirrel report --diffcounts a finding as fixed only when the current report no longer has it and the rule looked again (#1748, #1741 part 3): both audits are of the same site, the rule ran in both, and the current audit crawled the finding's page and the rule did not skip it there. A finding that is gone for any other reason is listed in a separate Not compared group with its reason and is not counted inremoved: its rule did not run, timed out or was skipped in the current audit (including by--target-url), or did not run in the baseline; its page was not crawled or was skipped; the audits cover different sites; or the current report is a JSON export read withreport --inputthat has noruleslist (any export from before schema 1.20) or a sampled list of the check's pages. For a rule that declares its check names, a run that answered only with a declared "not checked" check, and no clean check that clears the problem, is not compared either. The group appears in the console, text, markdown and llm diff, and in the JSON diff asnotComparedwithsummary.notCompared(both left out when the group is empty). The text formats also list there the findings whose superseding check was not checked, which the JSON diff keeps innotChecked, so the two counts can differ. Behaviour change: a finding that used to read as removed because its rule had no result in the later report, or its page was not crawled, is now not compared. Known limit: a finding keyed by an item that names a page, such as a short title or meta description, can still read as removed when the current audit did not crawl that page (#1835).- Published reports carry an optional
pageMapsection (the rows ofsquirrel pages, failed pages included), so the hosted API and MCP can list a stored report's pages (#701). Every publish fromsquirrel audit(with--publishor automatic) andsquirrel report --publishof a stored audit sends it; a report published from a JSON file has none, and when the page rows cannot be read the CLI warns and publishes without it. It is capped at 1,000 pages (shallowest first) withtruncated,storedandtotalcounts. When a report is too large to publish, issue samples are reduced first, and the page map is dropped (detail.pageMapDropped) only when the issue counts alone still do not fit. Core contracts gainPageMapSchema,PageMapRowSchemaandPAGE_MAP_PUBLISH_LIMITS. The public API docs gainGET /v1/reports/{id}/pages. - Cloud credit top-ups go up to $5,000 (was $1,000) and earn bonus credits above $100, on a curve that reaches 20% at $1,000 and stays a flat 20% above it, so $5,000 buys 600,000 credits. Base and bonus credits are quoted separately, and the credits docs list the schedule. Core contracts gain
topupQuote,topupBonusSchedule,TOPUP_BONUS_CURVEandTOPUP_SCHEDULE_USD, andCREDIT_TOPUP.maxUsdis 5,000.
Changed
- A broken link in site-wide chrome (the header, navigation or footer of most pages) is reported once, as its own check:
broken-links-sitewidefor internal links andbroken-external-links-sitewidefor confirmed broken external links, with the section and page count in the message ("1 broken internal link in the footer of 71 pages (4xx/5xx)") (#1772). Broken links in page content stay inbroken-linksandbroken-external-links, whose messages then say "in page content". Possibly broken external links are not split. A link is site-wide when at least 3 pages carry it in chrome and those pages are at least half of the crawled pages (HTML pages that answered with a 2xx status; a placement counts when the markup named it or the page classifier named it at 0.8 confidence or more), so a link on both pages of a 2 page site is not, and one footer link on 1 of 70 pages is not. Score effect: the score's issue density counts at most 20 items per check and page, so a site with more than 20 broken links split between content and chrome can score lower than before. Tracking keys: a finding tracked underbroken-linksorbroken-external-linksfor a link that now reads as site-wide continues under the-sitewidename, and back: the rules declare the two names as superseding each other, soreport --diffshows the move as a change, never as a fix. The published report's broken-link target sets (linkTargetSets) include both checks.
Update to this version
squirrelscan will auto-update, or run this command to update now: