Skip to content

Releases: auroraxo/docrot

docrot v1.8.0 — local-repo scanner + docrot-check action

Choose a tag to compare

@auroraxo auroraxo released this 12 Oct 03:40

Added

  • scan_local.py + tests (6) — local-repo scanner for CI and GitHub
    Action use. Same classification rules as scan.py (in-repo / missing /
    external / unresolvable) but operates on a checked-out tree, so a CI
    step can run the same engine on its own repository without a GitHub
    token. Headline figure: externalThirdPartyBroken + missingInRepo.
    test_scan_local.py covers a 9-image fixture mixing dead external,
    missing in-repo, and healthy refs; the live-CI path is gated by
    SKIP_LIVE_CHECKS=1.
  • CI: dogfoods auroraxo/docrot-check (warn-only) so the published
    engine scans the engine's own docs. Pinned to the action's v1 tag
    now that the tagged release exists.
  • README "Screened, not rot" section — explicit list of the three
    in-repo README.md images that look like dead rot (a favicon that
    points to a non-200, a local asset path that's only resolved by the
    docs site, and a sponsor placeholder) but are actually intentional
    and reproducible; documents the live host-aggregation result for
    deepwiki/repology/starchart so a future reader doesn't file a
    duplicate issue.
  • README "Known rot clusters" section — eight cluster hosts
    (travis-ci.org legacy, broken.stock, dead-knight, etc.) with the
    number of distinct target URLs and their live HTTP status, plus the
    upstream issues filed against the affected projects.

Changed

  • CI test matrix now runs test_scan_local alongside the existing
    test_docrot and test_version_drift suites (70 + 19 + 6 = 95 tests on
    Python 3.10/3.12).
  • docrot-check pin in the docs CI moved from a hard-coded commit
    SHA to the action's published v1 tag.

docrot v1.7.0 — reproducibility & community trust release

Choose a tag to compare

@auroraxo auroraxo released this 11 Oct 01:21

Changelog: 10 commits since v1.6.0. Scanner behavior and published v8 numbers are unchanged — this release is about trust and reproducibility.

Highlights:

  • 60-second reproduction section in the README: re-run a published Wave-3 finding (sml2h3/ddddocr, 26 broken external images) in one command with the committed scanner — numbers must match the dataset or "the rot moved — open an issue".
  • CI: GitHub Actions workflow running the 89-test stdlib suite on Python 3.10/3.12 for push and PR, with a README badge.
  • Community standards complete: MIT LICENSE, CONTRIBUTING.md, Contributor Covenant 2.1 Code of Conduct, CITATION.cff, bug/feature issue templates, SECURITY.md (private disclosure via GitHub Security Advisories).
  • Report page (codebyaurora.com/docrot/) now ships canonical, Open Graph, and Twitter card metadata.
  • Documentation: 300-repo v5→v8 scanner-audit section in the README; upstream outcomes updated (tensorflow#128150 fixed by merged PR tensorflow#128179 — third merged upstream fix).

Full diff: v1.6.0...main

docrot v1.6.0 — Scanner v8: two more phantom classes closed

Choose a tag to compare

@auroraxo auroraxo released this 29 Sep 18:05

v1.6.0 / Scanner v8: fence indent 0-7 + list-item-local pairing — two more phantom classes closed

Found during manual classification of the v7 rescan (before-publishing
rule, again): BOTH defects were phantoms inside the freshly produced v7
datasets. Nothing was published from v7.

  1. airbnb/javascript 'react/hello.jpg' (wave 2): the reference lives in a
    4-space-indented ```jsx fence inside a list item; GitHub renders it as
    code (verified in rendered HTML) but the fence regex only stripped
    indent 0-3. CommonMark allows up to 3 spaces BEFORE the list marker,
    so fences inside items legitimately sit deeper -> strip 0-7.

  2. jujumilk3 'alt' (wave 3): the code span's opener sits in one
    list item, content+closer after a blank line in the next; an odd
    backtick run in the first item shifted positional pairing and left the
    span content live. Pairing now splits at list-item starts
    (_pair_backtick_runs), still paragraph-local within items.

Schema version 7 -> 8. Suite 87 -> 89 (both real-file shapes as
regressions; the jujumilk3 fixture topology verified against GitHub
HTML: that item renders ).

Also ships tools/synthesize_v8.py: 300-repo v5->v6->v7->v8 synthesis
with hard expectation gates (E1a airbnb 0, E1b jujumilk3 2, E1c skills
0, E2 webpack 327) committed BEFORE any v8 result exists; exit 2 on
incomplete inputs, exit 3 blocks publication on red.

docrot v1.5.2 — triple-newline pairing edge closed

Choose a tag to compare

@auroraxo auroraxo released this 29 Sep 14:55

Residual edge in the v1.5.1 paragraph-local inline-code pairing, found while re-reviewing the fix itself: a content part starting with a single newline (triple-newline sequences) was misrouted as a blank-line separator and skipped pairing — the phantom-ref class survived in that corner (reproduced with a fixture, leaked p.png). Separator detection now requires a full blank-line match. Suite 87 green. The running 300-repo v7 rescan is being restarted under this release so the published v7 datasets carry the fully closed class.

docrot v1.5.1 — Scanner v7: phantom reference class closed

Choose a tag to compare

@auroraxo auroraxo released this 29 Sep 14:34

v1.5.1 — Scanner v7: CommonMark inline-code pairing

Found by the manual-verification rule, before anything was published: while classifying the wave-2/wave-3 v6 rot-set movers, anthropics/skills carried a "missing" target path from flow root — which is actually a code example in eval-hillclimb.md (`![](<path from flow root>)`). GitHub renders it as <code> (verified against the rendered HTML); scanner v6 counted it as a broken image. Root cause: the old regex paired backtick runs positionally ((+).*?\1`); real documents interleave run lengths (stray single ticks around triple-tick literals), parity flipped mid-document, and span content survived stripping.

Fix: equal-length run pairing per CommonMark, paragraph-local — a code span never crosses a blank line. Verified against the real 68 KB file (phantom gone), the webpack README at its scanned commit (no regression; all reference-style badge defs still resolve), plus 4 new regression tests.

Honesty note: the wave-2 v6 dataset published today contains exactly this one known phantom. A 300-repo v7 rescan (all three waves) is starting now and supersedes the v6 wave datasets; the public story is not updated until that synthesis is complete and every rot-set mover is verified one by one.

Dataset schema version 6 → 7. Suite 82 → 86 green.

docrot v1.5.0 — Scanner v6: reference-style images counted

Choose a tag to compare

@auroraxo auroraxo released this 29 Sep 09:51

v1.5.0 — Scanner v6: reference-style images are counted

Found by a scanner-vs-API parity probe: the paid API's Markdown extractor already consumed [label]: url definitions; the open-source scanner silently skipped ![alt][label] uses — under-counting references in repos that use them (false-negative class; the mirror image of the v1.4.0 comment find).

Fix: full, collapsed, and shorthand uses resolve against their definitions. Conservative guards: link-only definitions are not images; unresolved uses produce nothing; labels case-insensitive; code/comment strips apply as before. Dataset schema version 5 → 6.

Tests: 8 new (resolve ×3, link-only exclusion, unresolved, case-fold, code-block, comment); suite 74 → 82 green.


Correction (2026-09-29, same day): this release was initially tagged on a commit where the new tests raised 8 NameErrors (unqualified extract_image_refs call; the red suite run was not heeded before shipping). Product code was unaffected and separately verified. The tag is repointed to include the test fix, the suite is verified 82/82 on the tagged commit, and the CHANGELOG carries the public correction bullet.

docrot v1.4.0 — HTML comments no longer counted as image references

Choose a tag to compare

@auroraxo auroraxo released this 28 Sep 14:14

v1.4.0 — HTML comments are no longer counted as image references

Fix: image-looking syntax inside <!-- ... --> comments no longer enters the reference dataset. Comment content is never rendered — the fourth false-positive family this project has closed (examples/code → entities → fenced & inline code in the API → comments).

Found by the parity ritual: the paid API (docrot-scan-api v1.3.0) strips HTML comments in all three extractors; checking scanner↔API parity pointed back at the scanner itself, which still counted them.

Implementation: strip_html_comments blanks each comment with same-length whitespace (newlines preserved), wired into extract_image_refs after strip_code.

Dataset integrity: every upstream finding in waves 1–3 was hand-verified before filing, so no report is affected; only aggregate reference counts may include a small number of commented-out images. The outcomes ledger is unchanged.

Verification: repro before (commented ![dead](…) flagged as reference), clean after; 2 new regression tests — suite 72 → 74 green.

docrot v1.3.1 — tier chart + mixed-basis correction

Choose a tag to compare

@auroraxo auroraxo released this 28 Sep 03:51

v1.3.1 — tier chart + a public correction

New: the wave-3 report section now ends with "The same finding, drawn" — an inline SVG (no JS, no external requests) comparing the three measured tiers on like-for-like metrics: rot share per 100 scanned (26% / 27% / 30%) and third-party share of unique images (53% / 31% / 57%). Building the chart is what surfaced the bug below.

Correction (the datasets were right, the prose wasn't): earlier text compared shares across different bases — README said "77% vs 29%" (external-per-unique-image vs third-party-per-reference), the field log said "77% vs 50%", and the wave-2 report section even printed the self-contradictory "77% external vs 77%". Like for like, the true story is:

  • external share of unique images: 77% → 77% → 75% (flat across tiers)
  • third-party share of unique images: 53% → 31% → 57% (swings with where a corpus's outside images live)
  • third-party share of references: 29% → 19% → 48%

All affected sentences in README, the live report, and the field log now carry the corrected numbers with a visible correction note. Every JSON dataset was and remains correct; no number in any finding or issue was affected — this was a prose-comparison error in the project's own narrative, caught by the project's own new chart.

Tests: 72 (+3 covering the tier chart: value order, labels, absence with a single tier).

docrot v1.3.0 — Wave-3 report section, 3-tier empirical proof, and outcome receipts

Choose a tag to compare

@auroraxo auroraxo released this 28 Sep 02:17

What's new in v1.3.0

  • Wave-3 report section (generate_report.py): accepts an optional 6th CLI argument (wave3-results.json) and renders the companion section "A third wave: one star tier down" with its own KPIs, a 3-tier cross-wave narrative, and the per-wave findings table.
  • Empirical milestone: 300 repositories scanned across three tiers (top-100, ≥15k stars, 10k–15k stars). The share of repositories carrying at least one broken documentation image stays remarkably steady: 26/100 → 27/100 → 30/100. Rot is not a quirk of the absolute top of GitHub; it is an intrinsic property of documentation maintenance across star tiers.
  • Upstream outcomes (18 receipts):
    • sml2h3/ddddocr#317: all 26 off-repo images on author CDN cdn.wenanzhe.com return HTTP 404; sponsor table and captcha demos broken in READMEs.
    • Azure/azure-quickstart-templates#14882: all 892 CI/deployment status badges on azurequickstartsservice.blob.core.windows.net return HTTP 409 PublicAccessNotPermitted across 146 READMEs.
    • aalansehaiyang/technology-talk#84: author's personal docsite offercome.cn is completely unreachable (HTTPS timeout); 477 unique off-repo images dead across docs/md/**.
  • Documentation & tests: README updated with the full wave-3 results, record-rot analysis, and the 6-argument CLI signature. Suite expanded to 69 tests (+5 covering wave-3 report rendering, cross-wave narratives, error disclosure, and HTML escaping).
  • Live report: codebyaurora.com/docrot/ updated and deployed with md5 parity.

v1.2.0 — Scanner v5: HTML entity decode, corrected wave-2 dataset

Choose a tag to compare

@auroraxo auroraxo released this 27 Sep 20:13

Scanner v5 (237ca95)

HTML-entity-encoded <img src> attribute values were live-checked undecoded. Browsers unescape entities in attribute values before fetching, so a URL like ?v&#x3D;4&amp;s&#x3D;18 renders fine in every reader — but the scanner requested the raw string and recorded HTTP 400.

Fix: decode HTML img src values only (html.unescape); markdown refs pass through unchanged. Two regression tests added; suite 60/60.

Corrected wave-2 dataset (10839f1)

Rescanned the 100-repository wave-2 corpus under v5:

  • externalBroken 248 → 104
  • axios/axios 136 → 0: the entire block was CHANGELOG contributor avatars that were never broken
  • trekhleb/javascript-algorithms 40 → 32, rustdesk/rustdesk −1, jackfrued/Python-100-Days +1 (live drift between the two scans, verified individually)
  • missingInRepo 48 and unresolvable 11 unchanged — the three filed issues (PowerToys#50821, firecrawl#4776, flutter#193415) are in-repo cases and were never affected
  • NousResearch/hermes-agent recovered from the v4 transient fetch error (uniqueImages 9 → 15), validating the markdownFetchErrors contract

Published copy at codebyaurora.com/docrot/docrot-wave2.json replaced with md5 parity (f5c050ff774f2cab255aecba5b88456b).

The pattern

Third scanner-caused false-positive class found by auditing our own findings before publishing (after adev/ docs-site roots and silent fetch skips in v3/v4). Every headline number in this repository has now survived a "prove it is really broken" pass — and the corrections are public, not quietly patched.