Публічний реєстр
Звіт про здоров'я програмного забезпеченнясхема 0.26.0 · метрики 1.13.0 · 2026-07-21 23:33 UTC

yob / pdf-reader

The PDF::Reader library implements a PDF parser conforming as much as possible to the PDF specification from Adobe.

RubyMIT★ 1 925 зірок⑂ 284 форкиз черв. 2008 р.Переглянути на GitHub ↗

yob/pdf-reader має індекс здоров’я 59 зі 100, що відповідає смузі «Помірний». Найвищий показник — Community & Adoption (76/100), найнижчий — AI Readiness (40/100). Останнє оновлення було 6 днів тому. Більшість нещодавньої роботи виконує один учасник.

59
загалом / 100
Помірний

Індекс здоров'я програмного забезпечення

Метрики згруповано у зважені категорії на шкалі 1–100. Загальна оцінка починається як їхнє середнє; коли публічні дані активують Політику юрисдикцій високого ризику, рейтинг коригується й отримує верхню межу 49 («Під ризиком»). Готовність до ШІ не входить до індексу.

59
Відмінний85-100Зразковий; відповідає практично всім перевіреним критеріям
Добрий70-84Здоровий; незначні прогалини
Помірний50-69Прийнятний, але з помітними прогалинами; рекомендовано перевірку
У зоні ризику30-49Суттєві слабкі місця; впровадження потребує обережності
Критичний1-29Серйозні проблеми (покинутий, єдиний мейнтейнер, без базової гігієни)
ЖиттєздатністьСпільнота тавпровадженняСталість таврядуванняІнженернаякістьБезпекаГотовність доШІ

Профіль оцінок

Кожна вісь — окрема категорія. Форма важить більше, ніж середнє: здоровий об'єкт заповнює всю фігуру, тоді як профіль із піками та провалами означає, що сила в одному вимірі маскує ризик в іншому.

Власність

James HealyОсобистий обліковий запис
236 підписників143 публічні репозиторіїз квіт. 2008 р.

Цей репозиторій належить особистому обліковому запису. Проєкт з єдиним власником несе більший ризик безперервності, ніж підтримуваний організацією.

Пакетні екосистеми

РеєстрПакетВерсіяЗавантажень / місВерсіїОстання публікація
RubyGemspdf-reader2.15.1-64205 днів тому

Метрики за категоріями

Життєздатність

Чи живий проєкт — чи пишеться код і чи виходять релізи?

64Помірний · 22% загального індексу
Як обчислюється оцінка
36/36Свіжість push — останній push 6 дн. тому
10.4/36Ритм комітів — 15/52 тижнів із комітами
18/18Обсяг комітів — 121 комітів за останній рік
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10
Використані вхідні дані
commits_last_year121
human_commit_share1
days_since_last_push6
active_weeks_last_year15
Як обчислюється оцінка
16.2/27Випускає релізи — 64 тегів версій (без релізів GitHub)
16.2/36Свіжість релізів — останній реліз 205 дн. тому
12.6/27Ритм релізів — реліз кожні ~158,1 дн.
0/10OpenSSF Scorecard: Signed-Releases — немає даних
Використані вхідні дані
releases_count64
latest_release_tagv2.15.1
releases_from_tagsтак
days_since_latest_release205
mean_days_between_releases158,1
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: Signed-Releases. Залишкові ваги перенормовано.

Спільнота та впровадження

Чи має проєкт користувачів, завантаження, увагу та влаштовані умови для контриб’юторів?

76Добрий · 18% загального індексу
Як обчислюється оцінка
53.3/60Зірки — 1 925 зірок
20.4/25Форки — 284 форків
9.2/15Спостерігачі — 46 спостерігачів
Використані вхідні дані
forks284
stars1 925
watchers46
growth_stateorganic
growth_factor_pct100
Як обчислюється оцінка
22.5/22.5README
22.5/22.5Ліцензія — визнана ліцензія (MIT)
0/18Настанови CONTRIBUTING
0/13.5Кодекс поведінки
0/7.2Шаблон issue
0/6.3Шаблон PR
Використані вхідні дані
has_readmeтак
has_licenseтак
has_contributingні
has_issue_templateні
has_code_of_conductні
has_pull_request_templateні
Як обчислюється оцінка
80/80Сумарні завантаження — 109 562 630 завантажень за весь час у rubygems
0/20Залежні пакети в реєстрі — ця екосистема цього не повідомляє
Використані вхідні дані
packagespdf-reader
dependents
ecosystemsrubygems
total_downloads109 562 630
monthly_downloads
Виключено з оцінювання (немає даних або не застосовно): Залежні пакети в реєстрі. Залишкові ваги перенормовано.

Сталість та врядування

Чи переживе проєкт своїх людей — бас-фактор, реактивність, хто за ним стоїть і як супроводжуються пакети?

62Помірний · 24% загального індексу
Як обчислюється оцінка
9/54Бас-фактор — на 1 контриб’ютор(ів) припадає половина всіх комітів
2.4/22.5Розподіл комітів — головний контриб’ютор — автор 89% комітів
13.5/13.5Широта контриб’юторів — 61 контриб’юторів
10/10OpenSSF Scorecard: Contributors — project has 26 contributing companies or organizations
Використані вхідні дані
bus_factor1
contributors_sampled61
top_contributor_share0,893
Як обчислюється оцінка
35.9/46.8Вирішення issue — закрито 77% issue
31.8/38.3Прийняття PR — злито 282/339 вирішених PR
0/15OpenSSF Scorecard: Code-Review — Found 1/11 approved changesets -- score normalized to 0
Використані вхідні дані
merged_prs282
open_issues61
closed_issues201
issue_closed_ratio0,767
closed_unmerged_prs57
Як обчислюється оцінка
10/30Підтримка власника — особистий (користувацький) обліковий запис
0/20Верифікований домен — не застосовно до користувацьких облікових записів
17.1/25Охоплення власника — 236 підписників у yob
25/25Послужний список — 143 публічних репозиторіїв, вік облікового запису ~18 р.
Використані вхідні дані
followers236
owner_typeUser
is_verified
owner_loginyob
public_repos143
account_age_days6 664
Виключено з оцінювання (немає даних або не застосовно): Верифікований домен. Залишкові ваги перенормовано.
Як обчислюється оцінка
25/25Опубліковано й доступно — 1 пакет(ів) у rubygems
26/35Свіжість публікацій — остання публікація 205 дн. тому
20/20Історія версій — 64 опублікованих версій
20/20Не застарілий — активний, не deprecated і не yanked
Використані вхідні дані
packagespdf-reader
ecosystemsrubygems
any_deprecatedні
min_days_since_publish205

Інженерна якість

Чи наявні базові інженерні практики та документація?

40У зоні ризику · 20% загального індексу

Інженерні практики

40У зоні ризику
Як обчислюється оцінка
0/24Процеси CI
24/24Наявні тести
0/16Конфігурація лінтера
0/9.6Pre-commit-хуки
0/6.4.editorconfig
16/20OpenSSF Scorecard: CI-Tests — 8 out of 9 merged PRs checked by a CI test -- score normalized to 8
Використані вхідні дані
has_ciні
has_testsтак
has_editorconfigні
has_linter_configні
has_precommit_configні

Документація

40У зоні ризику
Як обчислюється оцінка
30/30README
0/25Каталог документації
0/15Сайт документації / домашня сторінка
10/10Опис репозиторію
0/10Теми
0/10Wiki
Використані вхідні дані
topics
has_wikiні
homepage
has_readmeтак
has_docs_dirні
has_descriptionтак

Безпека

Чи міцні видимі практики безпеки й ланцюга постачання, без непослабленої пов’язаності з юрисдикціями високого ризику?

51Помірний · 16% загального індексу

Стан безпеки

39У зоні ризику
Як обчислюється оцінка
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2/2.5CI-Tests — 8 out of 9 merged PRs checked by a CI test -- score normalized to 8
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 1/11 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 26 contributing companies or organizations
0/10Dangerous-Workflow — немає даних
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Ліцензія — license file detected
7.5/7.5Maintained — 30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — немає даних
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — немає даних
0/7.5Token-Permissions — немає даних
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Використані вхідні дані
sourceopenssf_scorecard
checks_evaluated14
scorecard_versionv5.5.0
checks_inconclusive4
scorecard_aggregate3,9
Виключено з оцінювання (немає даних або не застосовно): dangerous_workflow, packaging, signed_releases, token_permissions. Залишкові ваги перенормовано.
Як обчислюється оцінка
35/35Прямі залежності без відомих сповіщень — жодна пряма залежність не має відомих сповіщень
0/25Непрямі залежності без відомих сповіщень — транзитивний набір не відокремлюється від залежностей розробки й тестування в цьому обсязі
0/40Немає задавнених сповіщень — жодне сповіщення не має дати публікації
Використані вхідні дані
sourceosv
advisories0
affected_packages0
assessed_packages2
unassessed_packages13
affected_by_severitynone
direct_affected_packages0
Виключено з оцінювання (немає даних або не застосовно): Непрямі залежності без відомих сповіщень, Немає задавнених сповіщень. Залишкові ваги перенормовано. Звірено 2 резолвлених залежностей із OSV. 13 не вдалося оцінити — немає резолвленої версії, непідтримувана екосистема або поза межами звітованого переліку пакетів. Цей репозиторій не публікує пакета, який резолвить індекс, тож натомість оцінено граф залежностей репозиторію. Цей граф змішує закріплені версії для розробки й тестування зі справді постачаними залежностями, тож оцінюються лише задекларовані runtime-залежності; транзитивні знахідки подаються як контекст і в оцінку не входять. Досяжність не аналізується.

Готовність до ШІ

Наскільки репозиторій оснащений для розробки та супроводу за участі ШІ-агентів? Незалежний, експериментальний бейдж — вага 0.0, тож він подається окремо і не впливає на загальний індекс здоров'я.

40У зоні ризику · 0% загального індексу
Як обчислюється оцінка
0/45Інструкції для агентів — немає CLAUDE.md / AGENTS.md / правил редактора
0/15Машиночитана документація (llms.txt)
40/40Читабельна історія комітів — намір зазначено у 75 з 100 людських комітів (структурований заголовок або пояснювальний текст)
Використані вхідні дані
has_llms_txtні
legible_history_share0,75
agent_instruction_files
agent_instruction_max_bytes
Як обчислюється оцінка
0/18Розгортання однією командою
22/22Автоматизовані тести
0/11Конфігурація лінтера / форматера
0/11Статична перевірка типів
10/10Відтворюване середовище — Dockerfile
2/10Підтверджена практика роботи з агентами — 1 з останніх 100 комітів створено агентом або з його зазначенням
0/8Автоматизоване супроводження — автоматичних оновлень залежностей не виявлено
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Використані вхідні дані
has_nixні
has_testsтак
lockfiles
has_dockerfileтак
typed_languageні
bootstrap_files
has_devcontainerні
has_linter_configні
typecheck_configs
agent_commit_share0,01
toolchain_manifests
dependency_bot_commit_share0
Як обчислюється оцінка
0/45Типізований код — Ruby без конфігурації перевірки типів
54.6/55Керовані розміри файлів — 1/133 файлів вихідного коду понад 60 КБ
Використані вхідні дані
primary_languageRuby
largest_source_bytes63 485
source_files_sampled133
oversized_source_files1
Як обчислюється оцінка
0/40Схема API (OpenAPI/GraphQL/proto)
0/20Сервер MCP
40/40Придатні до запуску приклади — examples
Використані вхідні дані
example_dirsexamples
has_mcp_signalні
api_schema_files

Ключові факти

1 925зірок GitHub
61контриб'юторів
121комітів за останні 12 місяців
6днів від останнього пушу
64релізів
1бас-фактор
61відкритих issue
RubyGemsпакетних екосистем

Докладніше

Історія зірок і форків 1 925 ★ / 284 ⇿
1 925Зірки
284Форки
55Релізи

Коли додано кожну зірку й форк — зібрано з GitHub і згруповано за днями. Кумулятивне зростання розміщено просто над денними додаваннями, з яких воно складається, тож їх видно одне проти одного: рівномірне органічне накопичення виглядає зовсім інакше, ніж різкий короткочасний сплеск. Там, де цю різницю можна виміряти, її подано як автентичність росту.

Показано лише найновішу історію — цей репозиторій перевищує вікно збору, тож найраніша історія не захоплена.

04008001 2001 6002 0001 925274332009-032017-112026-07
Мажорні 2Мінорні 23Патчі 30

Кожна точка охоплює 16 днів.

OpenSSF Scorecard 3.9 / 10
3.9сукупно

Незалежна, не прив'язана до інструментів оцінка безпеки від відкритого проєкту OpenSSF Scorecard. Кожна перевірка винагороджує практику безпеки, а не інструмент конкретного постачальника. Перевірки, які Scorecard не зміг визначити, позначено н/д і виключено з оцінки безпеки (вони ніколи не зараховуються як нуль).Scorecard v5.5.0 · 2026-07-21 23:33 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
8CI-Tests8 out of 9 merged PRs checked by a CI test -- score normalized to 8
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 1/11 approved changesets -- score normalized to 0
10Contributorsproject has 26 contributing companies or organizations
н/дDangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10
н/дPackagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
н/дSigned-Releasesno releases found
н/дToken-PermissionsNo tokens found
10Vulnerabilities0 existing vulnerabilities detected
Прямі залежності 5
РеєстрПакетОбмеження версіїМаніфест
RubyGemssorbet0.6.12872Gemfile
RubyGemstapioca0.17.10Gemfile
RubyGemsspoomGemfile
RubyGemsrbs-inlineGemfile
RubyGemswebrickGemfile
Усі залежності 15

Повний розв'язаний набір залежностей із графа залежностей GitHub: 5 прямих і 10 непрямих (транзитивних) пакетів. Транзитивне замикання є повним, коли в репозиторії закомічено lockfile.

РеєстрПакетВерсіяЗв'язок
RubyGemsrbs-inlineпряма
RubyGemssorbet0.6.12872пряма
RubyGemsspoomпряма
RubyGemstapioca0.17.10пряма
RubyGemswebrickпряма
RubyGemsafmнепряма
RubyGemscaneнепряма
RubyGemshasheryнепряма
RubyGemsmorecaneнепряма
RubyGemspryнепряма
RubyGemsrakeнепряма
RubyGemsrdocнепряма
RubyGemsrspecнепряма
RubyGemsruby-rc4непряма
RubyGemsttfunkнепряма
Сповіщення про залежності 0

Цей репозиторій не публікує пакета, який розпізнає індекс, тож оцінено його власний граф залежностей — 2 пакетів, серед яких є й піниї розробки та тестування, що ніколи не постачаються: 0 мають відомі сповіщення, з них 0 прямі. 13 не вдалося оцінити — немає резолвленої версії, непідтримувана екосистема або поза наведеним переліком пакетів.

Жодне відоме сповіщення не стосується оцінених залежностей.

Сповіщення означає, що версія, записана в графі залежностей, потрапляє в уражений діапазон. Досяжність не аналізується, а граф містить піниї розробки й тестування — знахідка може стосуватися інструментів, а не поставленого коду.

Звіт у форматі JSON машиночитний
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 27880,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "HTML": 937,
        "Ruby": 586252,
        "Shell": 2785
      },
      "pushed_at": "2026-07-15T02:30:48Z",
      "created_at": "2008-06-03T01:11:36Z",
      "owner_type": "User",
      "updated_at": "2026-07-21T10:44:37Z",
      "description": "The PDF::Reader library implements a PDF parser conforming as much as possible to the PDF specification from Adobe.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Ruby",
      "significant_languages": [
        "Ruby"
      ]
    },
    "owner": {
      "blog": "http://yob.id.au",
      "name": "James Healy",
      "type": "User",
      "login": "yob",
      "company": null,
      "location": "Melbourne, Australia",
      "followers": 236,
      "avatar_url": "https://avatars.githubusercontent.com/u/8132?v=4",
      "created_at": "2008-04-22T07:49:16Z",
      "is_verified": null,
      "public_repos": 143,
      "account_age_days": 6664
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.15.1",
          "kind": "patch",
          "published_at": "2025-12-28T02:03:22Z"
        },
        {
          "tag": "v2.15.0",
          "kind": "minor",
          "published_at": "2025-08-13T12:14:34Z"
        },
        {
          "tag": "v2.14.1",
          "kind": "patch",
          "published_at": "2025-02-04T00:11:38Z"
        },
        {
          "tag": "v2.14.0",
          "kind": "minor",
          "published_at": "2025-01-29T02:59:05Z"
        },
        {
          "tag": "v2.13.0",
          "kind": "minor",
          "published_at": "2024-11-02T00:33:54Z"
        },
        {
          "tag": "v2.12.0",
          "kind": "minor",
          "published_at": "2023-12-26T01:27:58Z"
        },
        {
          "tag": "v2.11.0",
          "kind": "minor",
          "published_at": "2022-10-26T11:13:32Z"
        },
        {
          "tag": "v2.10.0",
          "kind": "minor",
          "published_at": "2022-05-11T22:49:11Z"
        },
        {
          "tag": "v2.9.2",
          "kind": "patch",
          "published_at": "2022-02-20T00:07:15Z"
        },
        {
          "tag": "v2.9.1",
          "kind": "patch",
          "published_at": "2022-02-04T10:52:37Z"
        },
        {
          "tag": "v2.9.0",
          "kind": "minor",
          "published_at": "2022-01-24T13:01:24Z"
        },
        {
          "tag": "v2.8.0",
          "kind": "minor",
          "published_at": "2021-12-28T12:17:48Z"
        },
        {
          "tag": "v2.7.0",
          "kind": "minor",
          "published_at": "2021-12-13T13:07:44Z"
        },
        {
          "tag": "v2.6.0",
          "kind": "minor",
          "published_at": "2021-11-12T12:08:55Z"
        },
        {
          "tag": "v2.5.0",
          "kind": "minor",
          "published_at": "2021-06-06T00:02:18Z"
        },
        {
          "tag": "v2.4.2",
          "kind": "patch",
          "published_at": "2021-01-28T11:42:39Z"
        },
        {
          "tag": "v2.4.1",
          "kind": "patch",
          "published_at": "2020-09-24T04:08:29Z"
        },
        {
          "tag": "v2.4.0",
          "kind": "minor",
          "published_at": "2019-11-21T12:58:09Z"
        },
        {
          "tag": "v2.3.0",
          "kind": "minor",
          "published_at": "2019-11-07T03:00:40Z"
        },
        {
          "tag": "v2.2.1",
          "kind": "patch",
          "published_at": "2019-07-27T13:26:30Z"
        },
        {
          "tag": "v2.2.0",
          "kind": "minor",
          "published_at": "2018-12-18T11:01:05Z"
        },
        {
          "tag": "v2.1.0",
          "kind": "minor",
          "published_at": "2018-02-15T00:02:51Z"
        },
        {
          "tag": "v2.0.0",
          "kind": "major",
          "published_at": "2017-02-25T04:35:34Z"
        },
        {
          "tag": "v1.4.1",
          "kind": "patch",
          "published_at": "2017-01-01T14:08:15Z"
        },
        {
          "tag": "v1.4.0",
          "kind": "minor",
          "published_at": "2016-02-22T11:58:29Z"
        },
        {
          "tag": "v1.3.3",
          "kind": "patch",
          "published_at": "2013-04-07T06:36:12Z"
        },
        {
          "tag": "v1.3.2",
          "kind": "patch",
          "published_at": "2013-02-26T10:49:29Z"
        },
        {
          "tag": "v1.3.1",
          "kind": "patch",
          "published_at": "2013-02-12T02:48:58Z"
        },
        {
          "tag": "v1.3.0",
          "kind": "minor",
          "published_at": "2012-12-29T23:43:58Z"
        },
        {
          "tag": "v1.2.0",
          "kind": "minor",
          "published_at": "2012-08-30T14:20:56Z"
        },
        {
          "tag": "v1.1.1",
          "kind": "patch",
          "published_at": "2012-05-09T06:06:18Z"
        },
        {
          "tag": "v1.1.0",
          "kind": "minor",
          "published_at": "2012-03-25T03:49:49Z"
        },
        {
          "tag": "v1.0.0",
          "kind": "major",
          "published_at": "2012-01-16T11:01:44Z"
        },
        {
          "tag": "v0.10.1",
          "kind": "patch",
          "published_at": "2011-10-20T11:57:51Z"
        },
        {
          "tag": "v0.10.0",
          "kind": "minor",
          "published_at": "2011-07-06T09:55:22Z"
        },
        {
          "tag": "v0.9.3",
          "kind": "patch",
          "published_at": "2011-07-02T03:55:17Z"
        },
        {
          "tag": "v0.9.2",
          "kind": "patch",
          "published_at": "2011-04-24T02:16:01Z"
        },
        {
          "tag": "v0.9.1",
          "kind": "patch",
          "published_at": "2010-12-21T01:43:36Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2010-11-20T02:49:14Z"
        },
        {
          "tag": "v0.8.6",
          "kind": "patch",
          "published_at": "2010-08-26T17:30:25Z"
        },
        {
          "tag": "v0.8.5",
          "kind": "patch",
          "published_at": "2010-04-11T01:33:08Z"
        },
        {
          "tag": "v0.8.4",
          "kind": "patch",
          "published_at": "2010-03-29T09:15:04Z"
        },
        {
          "tag": "v0.8.3",
          "kind": "patch",
          "published_at": "2010-02-14T04:43:47Z"
        },
        {
          "tag": "v0.8.2",
          "kind": "patch",
          "published_at": "2010-01-01T08:45:44Z"
        },
        {
          "tag": "v0.8.1",
          "kind": "patch",
          "published_at": "2009-11-27T06:18:34Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2009-11-19T14:40:43Z"
        },
        {
          "tag": "v0.7.7",
          "kind": "patch",
          "published_at": "2009-09-11T09:01:21Z"
        },
        {
          "tag": "v0.7.6",
          "kind": "patch",
          "published_at": "2009-08-28T01:56:46Z"
        },
        {
          "tag": "v0.7.5",
          "kind": "patch",
          "published_at": "2008-08-27T00:12:08Z"
        },
        {
          "tag": "v0.7.4",
          "kind": "patch",
          "published_at": "2008-08-07T03:42:09Z"
        },
        {
          "tag": "v0.7.3",
          "kind": "patch",
          "published_at": "2008-06-11T04:07:35Z"
        },
        {
          "tag": "v0.7.2",
          "kind": "patch",
          "published_at": "2008-05-20T07:25:24Z"
        },
        {
          "tag": "v0.7.1",
          "kind": "patch",
          "published_at": "2008-05-11T12:02:40Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2008-05-06T05:09:34Z"
        },
        {
          "tag": "v0.6.2",
          "kind": "patch",
          "published_at": "2008-03-22T06:10:13Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2008-03-21T09:25:41Z"
        },
        {
          "tag": "v0.5.1",
          "kind": "patch",
          "published_at": "2008-01-01T12:07:47Z"
        },
        {
          "tag": "0.1.1",
          "kind": "patch",
          "published_at": "2011-07-06T10:06:09Z"
        },
        {
          "tag": "0.1.0",
          "kind": "minor",
          "published_at": "2011-07-04T14:26:48Z"
        },
        {
          "tag": "0.0.6",
          "kind": "patch",
          "published_at": "2011-04-26T01:39:49Z"
        },
        {
          "tag": "0.0.4",
          "kind": "patch",
          "published_at": "2011-04-24T02:24:24Z"
        },
        {
          "tag": "0.0.3",
          "kind": "patch",
          "published_at": "2011-04-07T08:06:14Z"
        },
        {
          "tag": "0.0.2",
          "kind": "patch",
          "published_at": "2011-04-01T05:46:04Z"
        },
        {
          "tag": "0.0.1",
          "kind": "patch",
          "published_at": "2011-03-27T15:18:20Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "578db3d49b9cfc458b186915896ae29f62ccd126",
          "body": "In some rare situations, Encoding#to_utf8 was returning invalid utf8\nstrings. That's not the goal, pdf-reader should always return valid utf8\nwhen it claims to. The problem is that we can't always trust the\ndifference tables pdf producing apps provide. In this particular case,\nwe can't blindly take \n[…]\n was partially fixed in #604, but adding the integration spec\nexposed that a further fix was required.\n\nI don't love the style here, but the test is green so I'll commit it. I\ncan tidy the code later.",
          "is_bot": false,
          "headline": "Avoid returning invalid utf8 from Encoding#to_utf8 (#605)",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-07-15T02:30:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "48278303b004f3324f5cefd100b80f88b6277d62",
          "body": "In some rare situations, Encoding#to_utf8 was returning invalid utf8 strings.\nThat's not the goal, pdf-reader should always return valid utf8 when it claims\nto. The problem is that we can't always trust the difference tables pdf\nproducing apps provide. In this particular case, we can't blindly take\n\n[…]\n was partially fixed in #604, but adding the integration spec exposed\nthat a further fix was required.\n\nI don't love the style here, but the test is green so I'll commit it. I can\ntidy the code later.",
          "is_bot": false,
          "headline": "Avoid returning invalid utf8 from Encoding#to_utf8",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-07-15T02:24:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e57131e391224cbc6cc13ede349304247df88b4c",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'pr/604'",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-07-15T01:11:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1b69da828ab62da89197bf5050a14d91d980ed98",
          "body": null,
          "is_bot": false,
          "headline": "coerce this unpacked value into an integer to keep sorbet happy",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-07-15T01:10:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fea46b5272d445fb12fc767257924c7449589381",
          "body": "…unknown-char box\n\nSigned-off-by: Sai Asish Y <say.apm35@gmail.com>",
          "is_bot": false,
          "headline": "Replace invalid Unicode code points from differences tables with the …",
          "author_name": "Sai Asish Y",
          "author_login": "SAY-5",
          "committed_at": "2026-07-10T20:22:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "62cd78c2d8fee6c9554dadeceff04ee99e0b8361",
          "body": "…lation! (#601)\n\n`process_glyph_displacement` was allocating a new `TransformationMatrix`\non every character painted. Adding `prepend_translation!`` allows\nin-place mutation\n\nAlso applied to `move_text_position` to save an allocation per\ntext-position move.\n\nA small reduction in object allocations w\n[…]\ntex.pdf\n            pdflatex    35.344M memsize (   160.000  retained)\n                       433.088k objects (     4.000  retained)\n                        50.000  strings (     2.000  retained)\n```",
          "is_bot": false,
          "headline": "Eliminate TransformationMatrix allocation per glyph via prepend_trans…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:36:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2e6cf0433a5f1bab164ead4b17223f1c742f929b",
          "body": "…lation!\n\n`process_glyph_displacement` was allocating a new `TransformationMatrix` on every character painted.\nAdding `prepend_translation!`` allows in-place mutation\n\nAlso applied to `move_text_position` to save an allocation per text-position move.",
          "is_bot": false,
          "headline": "Eliminate TransformationMatrix allocation per glyph via prepend_trans…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:33:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e87095b0641f79e1b87c8626aca4af195359576d",
          "body": "…(#600)\n\n`\"#{id}:#{gen}\".hash` created a String on every Hash key lookup. Use\n`(id << 16) ^ gen` for a collision-resistant integer hash with zero\nallocations.\n\nA small reduction in object allocations when run on MRI 3.4.9:\n\n* `cairo-unicode.pdf`: 179k -> 174k allocations (~2% reduction)\n* `pdflatex.\n[…]\ntex.pdf\n            pdflatex    41.972M memsize (   160.000  retained)\n                       515.939k objects (     4.000  retained)\n                        50.000  strings (     2.000  retained)\n```",
          "is_bot": false,
          "headline": "Eliminate String allocation in Reference#hash via integer arithmetic …",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:27:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9d90633a11e0188a13978cb323c9e589b790ad28",
          "body": "\"#{id}:#{gen}\".hash created a String on every Hash key lookup.\nUse (id << 16) ^ gen for a collision-resistant integer hash with zero\nallocations.",
          "is_bot": false,
          "headline": "Eliminate String allocation in Reference#hash via integer arithmetic",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:25:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a5457a11d5c8542e4abeecfa18fa8214056b0eae",
          "body": "…eam op (#599)\n\n`parse_token` was calling `Token.new(token)` for every operator\nrecognised in the operators hash. Since PDF content streams repeat a\nsmall fixed set of operators (Tj, BT, ET, cm, Td, …) many times, a\nclass-level `INTERNED_TOKENS` hash now caches each unique Token after it\nis created \n[…]\ntex.pdf\n            pdflatex    42.562M memsize (   160.000  retained)\n                       530.697k objects (     4.000  retained)\n                        50.000  strings (     2.000  retained)\n```",
          "is_bot": false,
          "headline": "Intern operator Token objects to avoid one allocation per content-str…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:20:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "aeedf61395c89480cec57d4b7b0a4121606b214e",
          "body": "…eam op\n\nparse_token was calling Token.new(token) for every operator recognised in the operators hash. Since\nPDF content streams repeat a small fixed set of operators (Tj, BT, ET, cm, Td, …) many times, a\nclass-level INTERNED_TOKENS hash now caches each unique Token after it is created the first time.",
          "is_bot": false,
          "headline": "Intern operator Token objects to avoid one allocation per content-str…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:16:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d1a6ab3cd120be95bd296043608fbef3aeb7d0a2",
          "body": "A variety of tweaks to text extraction related code to allocate fewer\nobjects. The difference is significant, the below benchmarks were run on\nMRI 3.4.9:\n\n* `cairo-unicode.pdf`: 305k -> 182k allocations (~40% reduction)\n* `pdflatex.pdf`: 731K -> 540K allocations (~26% reduction)\n* `prince1.pdf`: 59k\n[…]\ntex.pdf\n            pdflatex    42.946M memsize (     0.000  retained)\n                       540.417k objects (     0.000  retained)\n                        50.000  strings (     0.000  retained)\n```",
          "is_bot": false,
          "headline": "Reduce object allocations in various text extraction related code (#598)",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:09:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4501d5aa54de69a48275b2bf57f5b1962d00be85",
          "body": "Multiple fonts often share the same encoding (e.g. StandardEncoding). Previously each Encoding\ninstance would read and parse the same file, allocating hundreds of objects per load. Cache the built\nHash per file path in FILE_MAPPINGS, and just dup the cached result for each instance.",
          "is_bot": false,
          "headline": "Cache parsed encoding file mappings to avoid repeated file loads",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:07:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ea4950b9dfa12e862e0cf194cea196e0eab67cd5",
          "body": "`_m, single_byte, unicode = *l.match(...)` created 2 Arrays per line,\n`(MatchData#to_a + nil splat)` and `\"0x#{...}\"` interpolated 2 Strings per matching line.\nUse `=~` with $1/$2 to eliminate these allocs.",
          "is_bot": false,
          "headline": "Eliminate splat Array and hex interpolations in Encoding#load_mapping",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:05:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3e158fd5843160ffbcb6226e691a8b202f200601",
          "body": "rect.contains?(run.origin) was calling TextRun#origin, which lazily allocates a Point per run.\nPrecompute the rect bounds once and compare run.x/run.y directly",
          "is_bot": false,
          "headline": "Avoid Point allocation per TextRun in BoundingRectangleRunsFilter",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:05:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "79c0b382b5ade874b52f297f375d12293f5e2e94",
          "body": "…oding\n\nEach Encoding#initialize called default_mapping which created 256 two-element [key,value] arrays to\npass to Hash[tuples]. Replace with a frozen class-level constant built once via each_with_object,\nand just dup it in initialize.",
          "is_bot": false,
          "headline": "Precompute DEFAULT_MAPPING constant to avoid 256 Array allocs per Enc…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:05:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a3a1dff4f60c76a3a6efb67f88f6e0919237e836",
          "body": "…ring_insert\n\nRange.new(index, end) allocated a Range object and String.new(needle) made an unnecessary copy for\nevery text run placed during to_s. Using the str[start, length]= slice form avoids both.",
          "is_bot": false,
          "headline": "Eliminate Range and String allocs per text run in PageLayout#local_st…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:05:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae09787ef0ac6a08b9917623e92ff9d840be2648",
          "body": "For CMap-mapped fonts (Identity-H, etc.) called with Integer glyph codes, to_utf8_via_cmap always\nends with cmap.decode(code).pack(\"U*\") — allocating a new String per call. Since glyph codes repeat\nheavily within a page, memoize the result in a per-font Hash to pay the pack cost only once per\nunique code.",
          "is_bot": false,
          "headline": "Cache UTF-8 strings per glyph code in Font#to_utf8 for CMap-mapped fonts",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T13:05:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f9bb002fbaa0e342508d13339d87df0c83f89cab",
          "body": "…EPOINTS\n\nHash#fetch(key, default) evaluates the default eagerly, so @map.fetch(c, []) was allocating a\nthrowaway [] on every decode call — even on cache hits. Replacing the default with a frozen constant\neliminates one Array per glyph in any CMap-mapped font.",
          "is_bot": false,
          "headline": "Avoid Array allocation on every CMap#decode call via frozen EMPTY_COD…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T12:50:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fafe48cad6e026504e490c1f8de2bc1b20a8ad2d",
          "body": "…font_size churn\n\nto_utf8_via_cmap was wrapping cmap.decode (already an Array) in another Array then flattening it — 2\nneedless allocations per glyph. Replaced with direct .pack and flat_map.\n\nAlso stopped invalidating @font_size per glyph: font_size depends only on trm.b/trm.d (scale/rotation),\nnot trm.e/f (translation) which is all that changes between glyphs.",
          "is_bot": false,
          "headline": "Eliminate 2 wasted Array allocs per glyph in to_utf8_via_cmap; stop @…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T12:49:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad65f9014288c40ad9ca9397ba6891e1be9a79b6",
          "body": "Every TextRun was eagerly allocating a Point for @origin, but the hot path\nonly accesses x and y directly. Now x/y are stored as plain numerics and\nthe Point is only created on demand (by bounding-rect filters and tests).",
          "is_bot": false,
          "headline": "Make TextRun#origin lazy to avoid allocating a Point per character",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T12:49:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "82cb9c3dab77e46dd31d6aba6adf9ffffc1a794e",
          "body": "Specs are green on both, lets keep them that way",
          "is_bot": false,
          "headline": "Add jruby 10.1 and truffelruby 34 to the build matrix (#597)",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T12:31:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1ce7e26508828df0af59daefd1eea6a7f2f6557a",
          "body": null,
          "is_bot": false,
          "headline": "Add jruby 10.1 and truffelruby 34 to the build matrix",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T12:29:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "93fc04a45d0b31ab279b62d29e43e6237fa15a0b",
          "body": "A variety of tweaks to this class to allocate fewer objects. The\ndifference is modest, mostly depending on how much the PDF uses hex\nstrings and names with `#xx` format. The below benchmarks were run on\nMRI 3.4.9:\n\n* `cairo-unicode.pdf`: 326k -> 305k allocations (~6% reduction)\n* `pdflatex.pdf`: 744\n[…]\ntex.pdf\n            pdflatex    46.900M memsize (     0.000  retained)\n                       731.675k objects (     0.000  retained)\n                        50.000  strings (     0.000  retained)\n```",
          "is_bot": false,
          "headline": "Reduce object allocations in PDF::Reader::Parser (#596)",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T12:23:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ae0b737682e3ac62643399177b5a5a1d5b85e2fc",
          "body": "prepare_hex_token already accumulates all hex chars as one token, so hex_string's str=\"\".dup + str<<token\nloop was an unnecessary copy. Use the token directly.\n\nAlso replace [str].pack('H*') with a cached @hex_pack_buffer=[\"\"] array to eliminate 9,624 Array\nallocations per cairo-unicode.pdf parse.",
          "is_bot": false,
          "headline": "Eliminate Array+String allocs in hex_string by reusing pack buffer",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T12:21:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a6561dda1a1d6e053db4578e875cc759a2a445f5",
          "body": "The vast majority of PDF names contain no #xx sequences, so dup+gsub was\nallocating two strings unnecessarily. Now we only gsub when '#' is present.",
          "is_bot": false,
          "headline": "Skip dup+gsub in pdf_name when no hex escape sequences present",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T12:07:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0d928231d753a6f41c5d4020036f5b371fc7d71a",
          "body": "Every numeric token (very common) was triggering a MatchData allocation via =~.\nSwitching to match?() avoids that object entirely.\n\nWe need a shim so the code continues to work on rubies 2.1 -> 2.3, and we don't avoid the allocation\nthere. That's OK though, compatibility is the goal on those old versions",
          "is_bot": false,
          "headline": "Use match? instead of =~ in parse_token to avoid MatchData allocation",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T12:07:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2dd38b9d3b1794fffe96e3631d89c8807d1fb4a6",
          "body": "A variety of tweaks to this class to make it allocate fewer objects. The\ndifference is significant, the below benchmarks were run on MRI 3.4.9:\n\n* `cairo-unicode.pdf`: 486k -> 326k allocations (~32% reduction)\n* `pdflatex.pdf`: 936K -> 744K allocations (~20%)\n* `prince1.pdf`: 162k -> 74K allocations\n[…]\n000  retained)                            \n                       744.293k objects (     0.000  retained)                            \n                        50.000  strings (     0.000  retained)\n```",
          "is_bot": false,
          "headline": "Reduce object allocations in PDF::Reader::Buffer (#595)",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:58:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "427338611242d2061510a964fb18fc0bfda4f1c2",
          "body": null,
          "is_bot": false,
          "headline": "Make changes in c2fb182 work on rubies 2.1 -> 2.3",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:56:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "640e7518bdcf27fd5314016eaace5dc2fedac5c7",
          "body": "…llocs\n\n`when *TOKEN_WHITESPACE` expands the array via splat on every loop iteration,\nallocating a new Array each time. Inlining the 6 byte values directly into\nthe when clause eliminates ~105k Array allocations per cairo-unicode.pdf parse.",
          "is_bot": false,
          "headline": "Inline TOKEN_WHITESPACE bytes in case/when to eliminate splat Array a…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:40:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4e2ab1afd817fa490952611a07326cb07448260a",
          "body": "…e_hex_token\n\nWhen a hex string closes normally with '>' (0x3E), byte.chr was allocating\na new String object. Branch explicitly on 0x3E to push the frozen '>' literal\ninstead; the rare non-'>' delimiter path keeps byte.chr.",
          "is_bot": false,
          "headline": "Avoid byte.chr String allocation on normal hex string close in prepar…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:40:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "249708030ec75e92460ea575e6c9a2dddfd670cc",
          "body": "The '/' case in prepare_regular_token was building a new Array on every\nPDF name token to check whether the next byte terminates the name.\nNAME_TERMINATOR_BYTES is computed once at class load time instead.",
          "is_bot": false,
          "headline": "Hoist [nil, 0x20, 0x0A] + TOKEN_DELIMITER array to a frozen constant",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:39:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4f7f90ab2c9d9d88d7fceb140db0efa2cb322aec",
          "body": "…ular_token\n\nRestructured the nil (EOF) case to push tok inline, and removed the trailing\n@tokens << tok guard. This lets us drop 10 unnecessary tok = \"\".dup resets\nthat fired whenever a non-empty token was followed by a delimiter.",
          "is_bot": false,
          "headline": "Eliminate dead tok = \"\".dup allocs per delimiter token in prepare_reg…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:39:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d785a7475d7fcc1f8a1a9a3d59fd462cfd377190",
          "body": "…prepare_regular_token\n\nbyte.chr allocates a new String per call; frozen string literals in a\nfrozen_string_literal: true file are interned and reused across calls.",
          "is_bot": false,
          "headline": "Replace byte.chr with frozen string literals for delimiter tokens in …",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:39:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3d743520b33141d4eb40bd63aad2e71f2edbd88d",
          "body": "…empty\n\nWhen hitting a delimiter with an empty tok accumulator, we were always allocating\na new empty string. Now we only allocate when tok had content and was pushed to\n@tokens (and thus can't be reused).",
          "is_bot": false,
          "headline": "Avoid \"\".dup allocation in prepare_regular_token when tok is already …",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:39:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c2fb18234174716b8e33ec1c35ba91dfed12b211",
          "body": "…hData allocation\n\nCalled on nearly every token pair, .match() was allocating a MatchData object each time.\nSwitching to .match?() returns true/false without allocating.",
          "is_bot": false,
          "headline": "Use match? instead of match in merge_indirect_reference to avoid Matc…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:39:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f8e802248db2bab7f7a09805139dee2b8508e1a4",
          "body": "add memory benchmarking script",
          "is_bot": false,
          "headline": "Merge pull request #594 from yob/allocations-benchmark",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:32:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ca4396f7fded76f82b2bfe4dc2173aebdd6b41e5",
          "body": "I'm interested in benchmarking how many objects pdf-reader allocates while parsing various files,\nand I'll use this in my experiments",
          "is_bot": false,
          "headline": "add memory benchmarking script",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-05-03T11:29:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7473650301f81393d4dc41a814e7121e59e0b461",
          "body": "Adjust the way CMaps with def operators are handled (592 witrh tweaks)",
          "is_bot": false,
          "headline": "Merge pull request #593 from yob/592-with-tweaks",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-29T12:25:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "52b531369f385d97915951692a26277c48f5e11b",
          "body": "In #592 (see previous commit) a fix for handing CMap parsing was provided.\nIt works well and the new test coverage was excellent, but on style grounds\nI wanted to tweak the solution a bit.\n\nI'd prefer not to give Parser an API that introduces temporal coupling. That\nis, the behaviour of the class wi\n[…]\nr that's needed to parse postscript CMaps. At least, it's not needed\nfor the test file we have.\n\nFinally, I fixed a few long lines while I was in their vicinity, so the can\nmax_violations has reduced.",
          "is_bot": false,
          "headline": "Adjust the way CMaps with `def` operators are handled",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-29T12:22:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "aa5ca9697428e60151877f354b046f770ec86303",
          "body": null,
          "is_bot": false,
          "headline": "Add support for PostScript def keywords in CMap parsing",
          "author_name": "Andrew Roberts",
          "author_login": "andrew-roberts-lp",
          "committed_at": "2026-04-23T22:24:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a417864f7363a8b6261e0c5416655fab4b5a089f",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'pr/591'",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-08T11:14:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "197b8a2b162057173fcca0d0fbf590cf0003f366",
          "body": null,
          "is_bot": false,
          "headline": "Allow one extra cane violation",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-08T11:11:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "26f0232312d407623242ea5dabd6a9db0bd59436",
          "body": "The existing workaround for PDFs that start numbering at 1 instead of 0\nincorrectly triggers when object 1 is a legitimate free entry within an\nxref section that correctly starts at 0. When triggered, it resets the\nobject counter to 0, causing all subsequent object IDs to be off by one.\nThis makes p\n[…]\n\nsection header started at 1. On subsequent entries, objid == 1 means\nit was incremented from 0 and object 1 is a real free entry.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix xref objid reset when object 1 is a legitimate free entry",
          "author_name": "Micah Buckley-Farlee",
          "author_login": "micahbf",
          "committed_at": "2026-04-07T15:40:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "78285f58ba676a48f59453479b64fa70496377d8",
          "body": "Support ActualText in marked content for text extraction",
          "is_bot": false,
          "headline": "Merge pull request #587 from 55728/support-actual-text-in-marked-content",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-06T01:27:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c36bb9ab83725fde9afa4e510bdcf6a7e18f5647",
          "body": "When ActualText is present in a BDC/EMC marked content span, use it instead of ToUnicode-derived text for text extraction.\nThis handles PDFs where font feature substitutions (e.g. tnum) produce incorrect ToUnicode CMap entries.\n\nUses EncodingUtils.string_to_utf8 for ActualText encoding conversion per PDF 32000-1:2008 §14.9.4.\n\nFixes #523",
          "is_bot": false,
          "headline": "Support ActualText in marked content for text extraction",
          "author_name": "Kenta Ishizaki",
          "author_login": "55728",
          "committed_at": "2026-04-05T06:17:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a32edc341e754b02413c136d527c22c3df91604",
          "body": "Improve UTF8 conversion of strings outside content streams",
          "is_bot": false,
          "headline": "Merge pull request #590 from yob/encoding-replacement-character",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-05T01:20:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "18344a187c4d31a27154ff6c720e12189e5d1bec",
          "body": null,
          "is_bot": false,
          "headline": "ensure all returned strings have a valid encoding",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-05T01:18:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0d5407a157dee832ba8da2bac8e1a19907277eea",
          "body": "PDF::Reader::EncodingUtils is used to convert strings outside content streams into\nUTF8. The input strings are either UTF16 (most common in 2026), or PDFDocEncoding.\n\nFor the latter we have general purpose mapping of content stream strings in PDF::Reader::Encoding,\nhowever we weren't correctly handing a variety of special mappings in strings\noutside content streams.\n\nThis fixes that, meaning we'll correctly convert characters like the EURO in the pdf\nmetadata of older PDFs that ue PDFDocEncoding",
          "is_bot": false,
          "headline": "Improve conversion of PDFDocEncoding strings outside content streams",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-05T01:18:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1295634456f0fd8f391605462348ce142cfd8f40",
          "body": "When converting a UTF16 string to UTF8, replace invalid bytes with `�` rather than\nraise an exception.\n\nThe vast majority of PDFs will have valid UTF16 strings, and I don't think it's worth\nbreaking the control flow of pdf-reader consumers by raising an exception",
          "is_bot": false,
          "headline": "Improve handling of UTF16 strings with invalid bytes",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-05T01:12:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b5d18921f62307fe22a48098c4fd081becb87fb9",
          "body": "Small improvements to EncodingUtils",
          "is_bot": false,
          "headline": "Merge pull request #589 from yob/text-encoding-improvements",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-05T00:29:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e0e30baed4908c514a5e6e7b1631590ccef9a109",
          "body": "* reduce allocations by saving the UTF16 BOM as a constant\n* reduce allocations by using a constant identifier for utf8 rather than a string\n* Use ruby's built-in tools to convert from UTF16 to UTF8. pdf-reader used to maintain\n  compatibility with ruby 1.8 so we were unable to use `String#encode()`, but now that\n  the minimum support ruby is 2.1, we can",
          "is_bot": false,
          "headline": "Small improvements to EncodingUtils",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-05T00:26:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ec3d4eca106eabe8d2979d9cde54d12c84302ef9",
          "body": "extract text encoding utilities to a dedicated class with specs",
          "is_bot": false,
          "headline": "Merge pull request #588 from yob/extract-encoding-utils",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-05T00:08:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ce3beffa870f778849a24c70e8a3bd6d540ae13c",
          "body": "I think we'll find these useful in other places, so I'm preemptively extracting them to somewhere\nthey can be called by other code",
          "is_bot": false,
          "headline": "extract text encoding utilities to a dedicated class with specs",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-04-05T00:05:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83cbcb77a992cd3bcd538b40c28172b74cd3cd7b",
          "body": "Update truffleruby specs from 33.0.0 -> 33.0.1",
          "is_bot": false,
          "headline": "Merge pull request #584 from yob/truffleruby-33-0-1",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-01-22T00:49:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d3b9e4dce85eb6fc57a04e7437d45eeb75c15365",
          "body": "In #583 we added truffleruby to the CI matrix, and in the process uncovered an upstream bug:\n\nhttps://github.com/truffleruby/truffleruby/issues/4106\n\nThat bug is now fixed in 33.0.1, so bump CI to use that.",
          "is_bot": false,
          "headline": "Update truffleruby specs from 33.0.0 -> 33.0.1",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-01-22T00:45:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9c5d57e0d4e06855954072d9f1ec154f75e4669f",
          "body": "Add truffleruby to the CI matrix",
          "is_bot": false,
          "headline": "Merge pull request #583 from yob/truffleruby",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-01-19T04:25:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e381b1b7e2b8a8cb29a3f71876e2fd731a654760",
          "body": "soft fail is fine, lets just see if it runs. I couldn't find a reasonable image\nto use on docker hub, so I've built a custom one using rbenv. Seems rbenv\nis a supported way to install truffleruby based on: https://truffleruby.dev/blog/truffleruby-33-is-released\n\nI had to reorder the way we parse invalid PDFs in specs. Calling `Page#fonts`\non one particular PDF triggered a regexp bug inside truffleruby",
          "is_bot": false,
          "headline": "Add truffleruby to the CI matrix",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-01-19T04:21:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e57c8f1b15cf689183d4a85828975e5f452c4ec0",
          "body": "Expand test coverage for PDF::Reader::CMap",
          "is_bot": false,
          "headline": "Merge pull request #582 from yob/more-cmap-tests",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-01-18T08:22:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a18ed95cbdd886b70e6c43f4f7cd50323d9e4615",
          "body": ".. and fix one bug along the way.\n\nA draft of the missing test coverage was generated by amp, and it identified\nthe bug. The proposed test structure didn't work for me though, so I significantly\nrefactored",
          "is_bot": false,
          "headline": "Expand test coverage for PDF::Reader::CMap",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2026-01-18T08:19:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b58039dd03921d3cac21386a0ffad17b925247e3",
          "body": "Dynamically generate external RBS signatures at gem build time",
          "is_bot": false,
          "headline": "Merge pull request #580 from yob/external-rbs-in-gem",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T22:34:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "113938fc6b9871714ef8ecc18d06c8667a2a7c72",
          "body": "We recently converted our type annotations to inline RBS comments, while\ncontinuing to use sorbet tooling for type checking and IDE integration, and continuing\nto distribute sorbet type signatures in the gem (as an extenral RBI file).\n\nThe RBS ecosystem doesn't natively support inline comments yet, \n[…]\nfer RBS tooling by distributing the gem with RBS style type annotations in\nan external RBS file.\n\nThe location of the sig files follows the docs in\nhttps://github.com/ruby/rbs/blob/v3.10.0/docs/gem.md",
          "is_bot": false,
          "headline": "Dynamically generate external RBS signatures at gem build time",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T22:26:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7aa78cf8229598340fbe0c4829e8580338886350",
          "body": null,
          "is_bot": false,
          "headline": "a few comment fixes",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T13:24:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d95588080492be26af455a2896caf521ad31162b",
          "body": null,
          "is_bot": false,
          "headline": "a few more type annotations",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T13:13:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bcaa421d4ef89337ccb6cc1d82001dbd0fbde037",
          "body": "Bump sorbet to the latest version",
          "is_bot": false,
          "headline": "Merge pull request #579 from yob/bump-sorbet",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T12:56:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2e7a9f79fb91399a568ed3f7cff2ace5c7551e13",
          "body": "... and make a couple of required fixes",
          "is_bot": false,
          "headline": "Bump sorbet to the latest version",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T12:54:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1ab4d38dcd0488509a0642fa27e4b87a01fbc259",
          "body": "Use Point class rather than [x,y] Arrays in more places",
          "is_bot": false,
          "headline": "Merge pull request #578 from yob/more-points",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T12:33:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a250fffcda4eeb39250da903e1afc135a0be0fc6",
          "body": "As I roll type hints out more broadly in this codebase, using `Array[Numeric]` to\nrepresent an (x,y) point is a hassle. When reading from an array like [0,1], the standard\nArray accessor methods can return a nil which makes sorbet unhappy and we need to\nstart adding guards to let sorbet know that th\n[…]\ntheir signature:\n\n* PageState#ctm_transform\n* PageState#ttm_transform\n\nInstead, I've soft deprecated them and added these alternatives:\n\n* PageState#ctm_transform_point\n* PageState#ttm_transform_point",
          "is_bot": false,
          "headline": "Use Point class rather than [x,y] Arrays in more places",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T12:30:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9e0b9349b378c37c11e2f72826a476becca635cc",
          "body": "Update a few commands to default to ruby 3.4",
          "is_bot": false,
          "headline": "Merge pull request #577 from yob/ruby-bumps",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T07:19:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3ca767e378d6330a312644a38acd958229a729dc",
          "body": "May as well use the next-to-latest ruby for:\n\n* running sorbet and cane in CI\n* as the default when running various commands locally in dev",
          "is_bot": false,
          "headline": "Update a few commands to default to ruby 3.4",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-29T07:04:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57d8abe1195219346fe42b79d7b2f0245ea954a1",
          "body": null,
          "is_bot": false,
          "headline": "Move unit specs into a folder structure that matches the code under test",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-28T02:20:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "544a01c097802bc94ff74567df18cbd8f56e5abf",
          "body": "On the old version I started getting this error:\n\n    $ bundle exec spoom srb sigs export\n    ...\n    Translating signatures from RBS to RBI...\n    Injecting extend T::Sig to lib/pdf-reader.rb...\n    Running Tapioca...\n    Error: bundle exec tapioca gem pdf-reader --no-doc --no-loc --no-file-header \n[…]\nr/local/bundle/gems/tapioca-0.17.7/lib/tapioca/runtime/trackers/required_ancestor.rb:55:in '<module:Helpers>': undefined method 'new' for module T::Module (NoMethodError)\n        prepend(Module.new do",
          "is_bot": false,
          "headline": "Update tapioca to the latest version",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-28T02:03:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "03ad935bc7ce5051f5caaed158ef658631112363",
          "body": null,
          "is_bot": false,
          "headline": "prepare for release",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-28T01:55:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "14e7215f859ecebb3f7716bbeb5719338e9877f1",
          "body": "Have another go at using gem.coop",
          "is_bot": false,
          "headline": "Merge pull request #576 from yob/gem.coop",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-28T01:47:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fa87d757f6754695e83a2b910f5b6ddea2e8dc07",
          "body": "First attempted in f75b0ce, but reverted in 2540e5f because it wasn't working\non the (admittedtly ancient) jruby 9.1.\n\nTry again but only on the Gemfile used for specs on recent-ish rubies.",
          "is_bot": false,
          "headline": "Have another go at using gem.coop",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-28T01:44:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a9bfe1b8718cacf591dd2e1dafacbb4d34f345e1",
          "body": "Add ruby 4.0 to the CI matrix",
          "is_bot": false,
          "headline": "Merge pull request #575 from yob/ruby-4-ci",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-28T01:39:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae593218d85eb68916ebd6b6447c194e35123c6c",
          "body": "v4.0 was released a few days ago: https://www.ruby-lang.org/en/news/2025/12/25/ruby-4-0-0-released/",
          "is_bot": false,
          "headline": "Add ruby 4.0 to the CI matrix",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-12-28T01:36:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3bc2510a10902949e8c9ff85786e17de2dec47fc",
          "body": "Skip invalid UTF-16 surrogate pairs in CMaps",
          "is_bot": false,
          "headline": "Merge pull request #574 from yob/invalid-cmap-surrogate",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-11-30T04:05:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f0f1a618675d7c3c4a96161b46b6a6a8c6990462",
          "body": "CMaps used as a ToUnicode mapping should only return valid Unicode codepoints,\nand the range 0xD800 -> 0xD8FF are not valid to return on their own. They\nindicate the start of a surrogate pair and should be followed by more hex chars.\n\nWhen they're not, lets just skip them from the mapping.\n\nAn existing spec had to be changed because it was asserting that an invalid\nsurrogate pair was being mapped.",
          "is_bot": false,
          "headline": "Skip invalid UTF-16 surrogate pairs in CMaps",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-11-30T04:03:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "42988a580bbbd817a043e0ad6d2e3049aba083f0",
          "body": "Tounicode fix",
          "is_bot": false,
          "headline": "Merge pull request #573 from yob/tounicode-fix",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-11-30T02:51:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25f5642b6fd25d128887599e5e9ccca9df1d8766",
          "body": "I've added a test case for the previous commit - a PDF where ToUnicode is\na PDF Name rather than a Stream containing a CMap.\n\nWith that in place, I decided to fixc it in a slightly different way - attempting\nto dereference the value, and only then silently skipping loading ToUnicode\nif it's not the expected type.\n\nThis means that we'll also catch the case where ToUnicode is an indirect\nobject that points to a non-stream",
          "is_bot": false,
          "headline": "Solve non-stream ToUnicode in a slightly different way",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-11-30T02:49:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d833e2263e6f613261d4d0872712f661d98d4030",
          "body": null,
          "is_bot": false,
          "headline": "Fix ToUnicode handling for symbolic fonts",
          "author_name": "Sergey Krylov",
          "author_login": "servn",
          "committed_at": "2025-11-30T02:49:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2540e5f40f3ed29eb7d8768738f166f6f217f480",
          "body": "This reverts commit f75b0ce392e5c7385b9f6b07f017796bc99a6dd5.\n\nIt was working great in CI, except on jruby 9.1 which throws an error when\nbundling:\n\n    Could not fetch specs from https://gem.coop/ due to underlying error <Received\n    fatal alert: handshake_failure (https://gem.coop/specs.4.8.gz)>\n\nFor now I just want the build to pass, so I'll revert and investigate later",
          "is_bot": false,
          "headline": "Revert \"Give gem.coop a go\"",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-11-30T02:48:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f75b0ce392e5c7385b9f6b07f017796bc99a6dd5",
          "body": null,
          "is_bot": false,
          "headline": "Give gem.coop a go",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-11-07T05:16:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ecaa285abe818646e4a96b6d247d84d9606e2664",
          "body": "Now that I need to generate the RBI file at release time, we need to install\ngems from the Gemfile. That means git, compiler, etc",
          "is_bot": false,
          "headline": "change release step to use a full ruby 3.4 image",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-13T12:14:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99a55fc93e4853d53f9beb44ac74450aeaff3928",
          "body": "It crashes if I have type definitions above the class like this, but works\nif I move it to be inside the class.\n\nSorta.\n\nIt no longer crashes, but the exported signatures for methods using these\ntypes in the sig come out as `untyped`. I can live with that for now, these\ntypes are definitely working with sorbet itself and ruby-lsp is detecting\nthem, it's just an RBI export issue",
          "is_bot": false,
          "headline": "Move back to an official release of spoom",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-13T12:10:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "61a80cdbff3602aa11ba4677f86184cc66280573",
          "body": null,
          "is_bot": false,
          "headline": "We can go back to an upstream release of spoom now",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-13T12:06:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b457579278c02a1924cae8ebbfa4ec09a7b194ed",
          "body": null,
          "is_bot": false,
          "headline": "Oops, I think I need to install spoom before using it here",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-13T12:04:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a899fee845de8cbd9e6c326a06a343142bb90aec",
          "body": null,
          "is_bot": false,
          "headline": "prepare for relesae",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-13T12:01:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "435942eef4df235ae9893fb5a9f1415fd8bd4782",
          "body": null,
          "is_bot": false,
          "headline": "remove unused config file for parlour",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-13T11:57:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b3155c08f887ea1b38052d014c1445a447c6fd16",
          "body": "Avoid infinite recursion when a PDF has a loop in the ancestorsof a Page object",
          "is_bot": false,
          "headline": "Merge pull request #567 from yob/fix-stack-overflow-in-page-ancestors",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-13T11:48:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "64023495ff94796eb49911d08dd3218bea1732c9",
          "body": "…age object\n\nEach page in a PDF is a single Object in a tree of Pages->Pages->Page objects, and\nthe page inherits properties from its ancestors right up the tree.\n\nWe had not protection against a malicious (or incompetently generated) PDF\nthat built an ancestor tree with a cyclic loop. As a result, \n[…]\n it, when walking up the tree to find all the ancestors keep a record\nof the ones we have seen and raise an error if we see one again.\n\nThanks to Yann @ Riema Labs for finding and reporting the issue.",
          "is_bot": false,
          "headline": "Avoid infinite recursion when a PDF has a loop in the ancestorsof a P…",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-10T10:57:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b26c5694d5c0f3ca80873545464308864384c3d9",
          "body": "This is getting easier now that I can do the types inline.\n\nI haven't changed the file to `typed: srtict` yet, because sorbet will insist\nthat I make this class a collection that's compatible with generics, and\nI'm not ready for teh changes that will require across the codebase",
          "is_bot": false,
          "headline": "Add more type annotations to ObjectHash class",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-10T10:30:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c08babcc90e413ada3c5e34835af6f5096116938",
          "body": "No changes to the code required",
          "is_bot": false,
          "headline": "change Parse to `typed: strict`",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-10T07:19:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e98890fb8383cb1c3057d88ad83659b4945541c3",
          "body": "Now that the types are inline this is nice and easy",
          "is_bot": false,
          "headline": "Change FontDescriptor to `typed: strict`",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-10T07:17:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bb13a4db3d5e3ca6119f007e5d42fb8e3a2c7618",
          "body": "Change xref.rb to `typed: strict`",
          "is_bot": false,
          "headline": "Merge pull request #568 from yob/typed-xref",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-10T07:08:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "18afd04b2128a40d337012fa5cf7d5622ccdd71d",
          "body": "Now that the types are inline, this is much easier to do",
          "is_bot": false,
          "headline": "Change xref.rb to `typed: strict`",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-10T06:56:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f25a3421a19f2af1e81372d000499cbf8f378d4b",
          "body": null,
          "is_bot": false,
          "headline": "change WidthCalculator from `typed: true` to `typed: strict`",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-10T02:58:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3a919df5be7842194863fda28697abe612ffe245",
          "body": null,
          "is_bot": false,
          "headline": "Change StandardKeyBuilder to `typed: strict`",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-10T02:17:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "13b2f135d99b3cb82b8e38b7d8e0ead6a65281ad",
          "body": "Convert two classes from `typed: true` to `typed: strict`",
          "is_bot": false,
          "headline": "Merge pull request #566 from yob/strict-typing",
          "author_name": "James Healy",
          "author_login": "yob",
          "committed_at": "2025-08-10T01:59:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 64,
      "commits_last_year": 121,
      "latest_release_at": "2025-12-28T02:03:22Z",
      "latest_release_tag": "v2.15.1",
      "releases_from_tags": true,
      "days_since_last_push": 6,
      "active_weeks_last_year": 15,
      "days_since_latest_release": 205,
      "mean_days_between_releases": 158.1
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "pdf-reader",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "rubygems",
          "matches_repo": true,
          "registry_url": "https://rubygems.org/gems/pdf-reader",
          "is_deprecated": false,
          "latest_version": "2.15.1",
          "repository_url": "https://github.com/yob/pdf-reader/tree/v2.15.1",
          "versions_count": 64,
          "total_downloads": 109562630,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2009-07-25T18:03:28Z",
          "latest_published_at": "2025-12-28T02:06:54.937000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 205
        }
      ]
    },
    "popularity": {
      "forks": 284,
      "stars": 1925,
      "watchers": 46,
      "fork_history": {
        "days": [
          {
            "date": "2009-03-16",
            "count": 1
          },
          {
            "date": "2009-06-17",
            "count": 1
          },
          {
            "date": "2009-09-14",
            "count": 1
          },
          {
            "date": "2009-12-13",
            "count": 1
          },
          {
            "date": "2010-02-12",
            "count": 1
          },
          {
            "date": "2010-03-09",
            "count": 1
          },
          {
            "date": "2010-04-24",
            "count": 1
          },
          {
            "date": "2010-08-04",
            "count": 1
          },
          {
            "date": "2010-11-03",
            "count": 1
          },
          {
            "date": "2011-02-09",
            "count": 1
          },
          {
            "date": "2011-02-14",
            "count": 1
          },
          {
            "date": "2011-03-28",
            "count": 1
          },
          {
            "date": "2011-06-05",
            "count": 1
          },
          {
            "date": "2011-07-22",
            "count": 1
          },
          {
            "date": "2011-07-27",
            "count": 1
          },
          {
            "date": "2011-08-13",
            "count": 1
          },
          {
            "date": "2011-08-17",
            "count": 1
          },
          {
            "date": "2011-08-19",
            "count": 1
          },
          {
            "date": "2011-09-20",
            "count": 1
          },
          {
            "date": "2011-10-06",
            "count": 1
          },
          {
            "date": "2011-11-06",
            "count": 1
          },
          {
            "date": "2011-11-15",
            "count": 1
          },
          {
            "date": "2011-12-04",
            "count": 1
          },
          {
            "date": "2011-12-19",
            "count": 1
          },
          {
            "date": "2012-01-09",
            "count": 1
          },
          {
            "date": "2012-01-14",
            "count": 1
          },
          {
            "date": "2012-01-26",
            "count": 1
          },
          {
            "date": "2012-02-17",
            "count": 1
          },
          {
            "date": "2012-04-17",
            "count": 1
          },
          {
            "date": "2012-04-20",
            "count": 1
          },
          {
            "date": "2012-05-12",
            "count": 1
          },
          {
            "date": "2012-06-11",
            "count": 1
          },
          {
            "date": "2012-07-05",
            "count": 1
          },
          {
            "date": "2012-07-24",
            "count": 1
          },
          {
            "date": "2012-07-27",
            "count": 1
          },
          {
            "date": "2012-07-29",
            "count": 1
          },
          {
            "date": "2012-08-07",
            "count": 1
          },
          {
            "date": "2012-09-10",
            "count": 1
          },
          {
            "date": "2012-09-18",
            "count": 1
          },
          {
            "date": "2012-11-06",
            "count": 2
          },
          {
            "date": "2012-12-17",
            "count": 1
          },
          {
            "date": "2013-01-02",
            "count": 1
          },
          {
            "date": "2013-01-13",
            "count": 1
          },
          {
            "date": "2013-01-14",
            "count": 1
          },
          {
            "date": "2013-01-28",
            "count": 1
          },
          {
            "date": "2013-02-15",
            "count": 1
          },
          {
            "date": "2013-03-06",
            "count": 1
          },
          {
            "date": "2013-03-22",
            "count": 1
          },
          {
            "date": "2013-03-24",
            "count": 1
          },
          {
            "date": "2013-04-25",
            "count": 1
          },
          {
            "date": "2013-04-27",
            "count": 1
          },
          {
            "date": "2013-05-08",
            "count": 1
          },
          {
            "date": "2013-05-16",
            "count": 1
          },
          {
            "date": "2013-05-24",
            "count": 1
          },
          {
            "date": "2013-06-23",
            "count": 1
          },
          {
            "date": "2013-07-02",
            "count": 1
          },
          {
            "date": "2013-07-15",
            "count": 1
          },
          {
            "date": "2013-07-19",
            "count": 1
          },
          {
            "date": "2013-08-01",
            "count": 1
          },
          {
            "date": "2013-08-13",
            "count": 1
          },
          {
            "date": "2013-08-22",
            "count": 1
          },
          {
            "date": "2013-09-06",
            "count": 1
          },
          {
            "date": "2013-10-01",
            "count": 1
          },
          {
            "date": "2013-10-16",
            "count": 1
          },
          {
            "date": "2013-10-30",
            "count": 1
          },
          {
            "date": "2013-12-31",
            "count": 1
          },
          {
            "date": "2014-01-20",
            "count": 1
          },
          {
            "date": "2014-02-17",
            "count": 1
          },
          {
            "date": "2014-03-10",
            "count": 1
          },
          {
            "date": "2014-03-28",
            "count": 1
          },
          {
            "date": "2014-04-10",
            "count": 1
          },
          {
            "date": "2014-04-21",
            "count": 1
          },
          {
            "date": "2014-05-15",
            "count": 1
          },
          {
            "date": "2014-05-19",
            "count": 1
          },
          {
            "date": "2014-06-03",
            "count": 1
          },
          {
            "date": "2014-06-13",
            "count": 1
          },
          {
            "date": "2014-06-25",
            "count": 1
          },
          {
            "date": "2014-07-27",
            "count": 1
          },
          {
            "date": "2014-08-03",
            "count": 1
          },
          {
            "date": "2014-08-09",
            "count": 1
          },
          {
            "date": "2014-08-21",
            "count": 1
          },
          {
            "date": "2014-09-16",
            "count": 1
          },
          {
            "date": "2014-10-10",
            "count": 1
          },
          {
            "date": "2014-10-12",
            "count": 1
          },
          {
            "date": "2014-10-16",
            "count": 1
          },
          {
            "date": "2014-11-10",
            "count": 1
          },
          {
            "date": "2014-12-09",
            "count": 1
          },
          {
            "date": "2014-12-17",
            "count": 1
          },
          {
            "date": "2014-12-22",
            "count": 1
          },
          {
            "date": "2014-12-25",
            "count": 1
          },
          {
            "date": "2015-01-08",
            "count": 1
          },
          {
            "date": "2015-03-08",
            "count": 1
          },
          {
            "date": "2015-03-11",
            "count": 1
          },
          {
            "date": "2015-03-18",
            "count": 1
          },
          {
            "date": "2015-03-20",
            "count": 1
          },
          {
            "date": "2015-03-26",
            "count": 1
          },
          {
            "date": "2015-04-04",
            "count": 1
          },
          {
            "date": "2015-04-08",
            "count": 1
          },
          {
            "date": "2015-06-19",
            "count": 1
          },
          {
            "date": "2015-06-30",
            "count": 1
          },
          {
            "date": "2015-07-07",
            "count": 1
          },
          {
            "date": "2015-07-24",
            "count": 1
          },
          {
            "date": "2015-08-08",
            "count": 1
          },
          {
            "date": "2015-08-18",
            "count": 1
          },
          {
            "date": "2015-09-23",
            "count": 1
          },
          {
            "date": "2015-10-05",
            "count": 1
          },
          {
            "date": "2015-10-06",
            "count": 1
          },
          {
            "date": "2015-10-15",
            "count": 1
          },
          {
            "date": "2015-10-22",
            "count": 1
          },
          {
            "date": "2015-11-11",
            "count": 1
          },
          {
            "date": "2015-11-22",
            "count": 1
          },
          {
            "date": "2015-12-07",
            "count": 1
          },
          {
            "date": "2015-12-14",
            "count": 1
          },
          {
            "date": "2015-12-21",
            "count": 1
          },
          {
            "date": "2015-12-27",
            "count": 1
          },
          {
            "date": "2016-01-02",
            "count": 1
          },
          {
            "date": "2016-02-16",
            "count": 1
          },
          {
            "date": "2016-02-19",
            "count": 1
          },
          {
            "date": "2016-03-07",
            "count": 1
          },
          {
            "date": "2016-03-19",
            "count": 1
          },
          {
            "date": "2016-03-22",
            "count": 1
          },
          {
            "date": "2016-03-29",
            "count": 1
          },
          {
            "date": "2016-04-10",
            "count": 1
          },
          {
            "date": "2016-04-22",
            "count": 1
          },
          {
            "date": "2016-06-02",
            "count": 1
          },
          {
            "date": "2016-07-14",
            "count": 1
          },
          {
            "date": "2016-08-30",
            "count": 1
          },
          {
            "date": "2016-09-11",
            "count": 1
          },
          {
            "date": "2016-09-20",
            "count": 1
          },
          {
            "date": "2016-10-03",
            "count": 1
          },
          {
            "date": "2016-10-31",
            "count": 1
          },
          {
            "date": "2016-11-17",
            "count": 1
          },
          {
            "date": "2016-12-20",
            "count": 2
          },
          {
            "date": "2016-12-24",
            "count": 1
          },
          {
            "date": "2017-02-22",
            "count": 1
          },
          {
            "date": "2017-03-14",
            "count": 1
          },
          {
            "date": "2017-03-16",
            "count": 1
          },
          {
            "date": "2017-03-18",
            "count": 1
          },
          {
            "date": "2017-03-31",
            "count": 1
          },
          {
            "date": "2017-04-18",
            "count": 1
          },
          {
            "date": "2017-05-20",
            "count": 1
          },
          {
            "date": "2017-05-30",
            "count": 2
          },
          {
            "date": "2017-06-01",
            "count": 1
          },
          {
            "date": "2017-07-04",
            "count": 1
          },
          {
            "date": "2017-07-07",
            "count": 1
          },
          {
            "date": "2017-07-12",
            "count": 1
          },
          {
            "date": "2017-08-10",
            "count": 1
          },
          {
            "date": "2017-08-14",
            "count": 1
          },
          {
            "date": "2017-08-15",
            "count": 1
          },
          {
            "date": "2017-09-15",
            "count": 2
          },
          {
            "date": "2017-09-28",
            "count": 1
          },
          {
            "date": "2017-09-29",
            "count": 1
          },
          {
            "date": "2017-10-18",
            "count": 1
          },
          {
            "date": "2017-10-31",
            "count": 1
          },
          {
            "date": "2017-11-11",
            "count": 1
          },
          {
            "date": "2017-12-13",
            "count": 1
          },
          {
            "date": "2017-12-20",
            "count": 1
          },
          {
            "date": "2018-02-02",
            "count": 1
          },
          {
            "date": "2018-02-21",
            "count": 1
          },
          {
            "date": "2018-02-28",
            "count": 1
          },
          {
            "date": "2018-03-02",
            "count": 1
          },
          {
            "date": "2018-03-27",
            "count": 1
          },
          {
            "date": "2018-07-03",
            "count": 1
          },
          {
            "date": "2018-07-24",
            "count": 1
          },
          {
            "date": "2018-09-06",
            "count": 1
          },
          {
            "date": "2018-11-25",
            "count": 1
          },
          {
            "date": "2018-11-27",
            "count": 1
          },
          {
            "date": "2019-01-01",
            "count": 1
          },
          {
            "date": "2019-01-07",
            "count": 1
          },
          {
            "date": "2019-01-08",
            "count": 1
          },
          {
            "date": "2019-02-20",
            "count": 1
          },
          {
            "date": "2019-04-24",
            "count": 1
          },
          {
            "date": "2019-06-03",
            "count": 1
          },
          {
            "date": "2019-06-25",
            "count": 3
          },
          {
            "date": "2019-06-26",
            "count": 1
          },
          {
            "date": "2019-07-06",
            "count": 1
          },
          {
            "date": "2019-07-12",
            "count": 1
          },
          {
            "date": "2019-07-18",
            "count": 1
          },
          {
            "date": "2019-08-02",
            "count": 1
          },
          {
            "date": "2019-08-22",
            "count": 1
          },
          {
            "date": "2019-11-11",
            "count": 1
          },
          {
            "date": "2019-11-15",
            "count": 1
          },
          {
            "date": "2019-11-19",
            "count": 1
          },
          {
            "date": "2019-11-24",
            "count": 1
          },
          {
            "date": "2019-11-26",
            "count": 1
          },
          {
            "date": "2019-12-15",
            "count": 1
          },
          {
            "date": "2020-01-02",
            "count": 1
          },
          {
            "date": "2020-01-30",
            "count": 1
          },
          {
            "date": "2020-02-11",
            "count": 1
          },
          {
            "date": "2020-02-17",
            "count": 1
          },
          {
            "date": "2020-03-19",
            "count": 1
          },
          {
            "date": "2020-04-10",
            "count": 1
          },
          {
            "date": "2020-05-31",
            "count": 1
          },
          {
            "date": "2020-07-28",
            "count": 1
          },
          {
            "date": "2020-09-05",
            "count": 1
          },
          {
            "date": "2020-11-19",
            "count": 1
          },
          {
            "date": "2021-01-30",
            "count": 1
          },
          {
            "date": "2021-06-01",
            "count": 1
          },
          {
            "date": "2021-06-03",
            "count": 1
          },
          {
            "date": "2021-08-16",
            "count": 1
          },
          {
            "date": "2021-09-03",
            "count": 1
          },
          {
            "date": "2021-10-03",
            "count": 1
          },
          {
            "date": "2021-10-06",
            "count": 1
          },
          {
            "date": "2021-10-16",
            "count": 1
          },
          {
            "date": "2021-10-21",
            "count": 1
          },
          {
            "date": "2022-01-07",
            "count": 1
          },
          {
            "date": "2022-01-12",
            "count": 1
          },
          {
            "date": "2022-02-05",
            "count": 1
          },
          {
            "date": "2022-02-10",
            "count": 1
          },
          {
            "date": "2022-02-21",
            "count": 1
          },
          {
            "date": "2022-03-02",
            "count": 1
          },
          {
            "date": "2022-03-25",
            "count": 1
          },
          {
            "date": "2022-04-03",
            "count": 1
          },
          {
            "date": "2022-04-27",
            "count": 1
          },
          {
            "date": "2022-05-04",
            "count": 1
          },
          {
            "date": "2022-05-11",
            "count": 1
          },
          {
            "date": "2022-05-31",
            "count": 1
          },
          {
            "date": "2022-07-12",
            "count": 1
          },
          {
            "date": "2022-08-10",
            "count": 1
          },
          {
            "date": "2022-08-23",
            "count": 1
          },
          {
            "date": "2022-08-24",
            "count": 1
          },
          {
            "date": "2022-10-05",
            "count": 1
          },
          {
            "date": "2022-10-09",
            "count": 1
          },
          {
            "date": "2022-11-29",
            "count": 1
          },
          {
            "date": "2023-01-13",
            "count": 1
          },
          {
            "date": "2023-03-16",
            "count": 1
          },
          {
            "date": "2023-04-05",
            "count": 1
          },
          {
            "date": "2023-04-18",
            "count": 1
          },
          {
            "date": "2023-05-11",
            "count": 1
          },
          {
            "date": "2023-05-18",
            "count": 1
          },
          {
            "date": "2023-07-28",
            "count": 1
          },
          {
            "date": "2023-10-10",
            "count": 1
          },
          {
            "date": "2023-10-19",
            "count": 1
          },
          {
            "date": "2023-10-25",
            "count": 1
          },
          {
            "date": "2023-11-21",
            "count": 1
          },
          {
            "date": "2023-12-14",
            "count": 1
          },
          {
            "date": "2023-12-15",
            "count": 1
          },
          {
            "date": "2024-01-26",
            "count": 1
          },
          {
            "date": "2024-02-05",
            "count": 1
          },
          {
            "date": "2024-02-20",
            "count": 1
          },
          {
            "date": "2024-03-15",
            "count": 1
          },
          {
            "date": "2024-03-25",
            "count": 1
          },
          {
            "date": "2024-05-30",
            "count": 1
          },
          {
            "date": "2024-06-05",
            "count": 1
          },
          {
            "date": "2024-06-28",
            "count": 1
          },
          {
            "date": "2024-08-28",
            "count": 1
          },
          {
            "date": "2024-09-17",
            "count": 1
          },
          {
            "date": "2024-12-01",
            "count": 1
          },
          {
            "date": "2024-12-12",
            "count": 1
          },
          {
            "date": "2025-01-11",
            "count": 1
          },
          {
            "date": "2025-01-30",
            "count": 1
          },
          {
            "date": "2025-02-03",
            "count": 1
          },
          {
            "date": "2025-03-13",
            "count": 1
          },
          {
            "date": "2025-04-14",
            "count": 1
          },
          {
            "date": "2025-04-23",
            "count": 1
          },
          {
            "date": "2025-06-13",
            "count": 1
          },
          {
            "date": "2025-06-24",
            "count": 1
          },
          {
            "date": "2025-07-19",
            "count": 1
          },
          {
            "date": "2025-07-24",
            "count": 1
          },
          {
            "date": "2025-08-06",
            "count": 1
          },
          {
            "date": "2025-11-11",
            "count": 2
          },
          {
            "date": "2025-11-21",
            "count": 1
          },
          {
            "date": "2026-02-19",
            "count": 1
          },
          {
            "date": "2026-04-07",
            "count": 1
          },
          {
            "date": "2026-04-20",
            "count": 1
          },
          {
            "date": "2026-04-23",
            "count": 1
          },
          {
            "date": "2026-07-10",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 274,
        "total_forks": 284
      },
      "star_history": {
        "days": [
          {
            "date": "2017-04-12",
            "count": 1
          },
          {
            "date": "2017-04-18",
            "count": 1
          },
          {
            "date": "2017-04-22",
            "count": 1
          },
          {
            "date": "2017-04-25",
            "count": 1
          },
          {
            "date": "2017-04-26",
            "count": 1
          },
          {
            "date": "2017-04-27",
            "count": 1
          },
          {
            "date": "2017-04-28",
            "count": 1
          },
          {
            "date": "2017-04-29",
            "count": 1
          },
          {
            "date": "2017-05-01",
            "count": 2
          },
          {
            "date": "2017-05-09",
            "count": 1
          },
          {
            "date": "2017-05-17",
            "count": 1
          },
          {
            "date": "2017-05-24",
            "count": 2
          },
          {
            "date": "2017-05-26",
            "count": 1
          },
          {
            "date": "2017-06-03",
            "count": 1
          },
          {
            "date": "2017-06-05",
            "count": 1
          },
          {
            "date": "2017-06-06",
            "count": 1
          },
          {
            "date": "2017-06-07",
            "count": 1
          },
          {
            "date": "2017-06-08",
            "count": 2
          },
          {
            "date": "2017-06-11",
            "count": 1
          },
          {
            "date": "2017-06-12",
            "count": 2
          },
          {
            "date": "2017-06-16",
            "count": 3
          },
          {
            "date": "2017-06-18",
            "count": 1
          },
          {
            "date": "2017-06-22",
            "count": 2
          },
          {
            "date": "2017-06-24",
            "count": 1
          },
          {
            "date": "2017-06-29",
            "count": 1
          },
          {
            "date": "2017-07-03",
            "count": 1
          },
          {
            "date": "2017-07-07",
            "count": 2
          },
          {
            "date": "2017-07-08",
            "count": 2
          },
          {
            "date": "2017-07-09",
            "count": 1
          },
          {
            "date": "2017-07-13",
            "count": 1
          },
          {
            "date": "2017-07-15",
            "count": 1
          },
          {
            "date": "2017-07-20",
            "count": 1
          },
          {
            "date": "2017-07-24",
            "count": 1
          },
          {
            "date": "2017-07-25",
            "count": 1
          },
          {
            "date": "2017-07-26",
            "count": 2
          },
          {
            "date": "2017-07-27",
            "count": 1
          },
          {
            "date": "2017-07-30",
            "count": 1
          },
          {
            "date": "2017-08-01",
            "count": 3
          },
          {
            "date": "2017-08-05",
            "count": 1
          },
          {
            "date": "2017-08-08",
            "count": 1
          },
          {
            "date": "2017-08-14",
            "count": 1
          },
          {
            "date": "2017-08-15",
            "count": 2
          },
          {
            "date": "2017-08-22",
            "count": 1
          },
          {
            "date": "2017-08-24",
            "count": 1
          },
          {
            "date": "2017-08-25",
            "count": 1
          },
          {
            "date": "2017-09-01",
            "count": 1
          },
          {
            "date": "2017-09-04",
            "count": 1
          },
          {
            "date": "2017-09-05",
            "count": 3
          },
          {
            "date": "2017-09-07",
            "count": 1
          },
          {
            "date": "2017-09-17",
            "count": 1
          },
          {
            "date": "2017-09-22",
            "count": 1
          },
          {
            "date": "2017-09-27",
            "count": 1
          },
          {
            "date": "2017-10-07",
            "count": 1
          },
          {
            "date": "2017-10-11",
            "count": 1
          },
          {
            "date": "2017-10-19",
            "count": 1
          },
          {
            "date": "2017-10-23",
            "count": 1
          },
          {
            "date": "2017-10-24",
            "count": 1
          },
          {
            "date": "2017-10-25",
            "count": 1
          },
          {
            "date": "2017-10-26",
            "count": 1
          },
          {
            "date": "2017-10-29",
            "count": 1
          },
          {
            "date": "2017-10-31",
            "count": 1
          },
          {
            "date": "2017-11-03",
            "count": 1
          },
          {
            "date": "2017-11-07",
            "count": 1
          },
          {
            "date": "2017-11-08",
            "count": 2
          },
          {
            "date": "2017-11-10",
            "count": 1
          },
          {
            "date": "2017-11-13",
            "count": 1
          },
          {
            "date": "2017-11-14",
            "count": 1
          },
          {
            "date": "2017-11-16",
            "count": 3
          },
          {
            "date": "2017-11-18",
            "count": 1
          },
          {
            "date": "2017-11-22",
            "count": 1
          },
          {
            "date": "2017-11-24",
            "count": 2
          },
          {
            "date": "2017-11-28",
            "count": 1
          },
          {
            "date": "2017-12-01",
            "count": 1
          },
          {
            "date": "2017-12-05",
            "count": 1
          },
          {
            "date": "2017-12-08",
            "count": 1
          },
          {
            "date": "2017-12-09",
            "count": 1
          },
          {
            "date": "2017-12-13",
            "count": 1
          },
          {
            "date": "2017-12-25",
            "count": 1
          },
          {
            "date": "2017-12-29",
            "count": 1
          },
          {
            "date": "2018-01-08",
            "count": 1
          },
          {
            "date": "2018-01-12",
            "count": 1
          },
          {
            "date": "2018-01-14",
            "count": 1
          },
          {
            "date": "2018-01-17",
            "count": 2
          },
          {
            "date": "2018-01-22",
            "count": 2
          },
          {
            "date": "2018-01-23",
            "count": 1
          },
          {
            "date": "2018-01-24",
            "count": 1
          },
          {
            "date": "2018-01-25",
            "count": 1
          },
          {
            "date": "2018-01-28",
            "count": 2
          },
          {
            "date": "2018-01-30",
            "count": 1
          },
          {
            "date": "2018-02-01",
            "count": 1
          },
          {
            "date": "2018-02-02",
            "count": 1
          },
          {
            "date": "2018-02-06",
            "count": 1
          },
          {
            "date": "2018-02-07",
            "count": 1
          },
          {
            "date": "2018-02-10",
            "count": 1
          },
          {
            "date": "2018-02-17",
            "count": 1
          },
          {
            "date": "2018-02-19",
            "count": 1
          },
          {
            "date": "2018-02-22",
            "count": 1
          },
          {
            "date": "2018-02-26",
            "count": 1
          },
          {
            "date": "2018-02-28",
            "count": 1
          },
          {
            "date": "2018-03-01",
            "count": 1
          },
          {
            "date": "2018-03-02",
            "count": 3
          },
          {
            "date": "2018-03-07",
            "count": 1
          },
          {
            "date": "2018-03-11",
            "count": 1
          },
          {
            "date": "2018-03-14",
            "count": 1
          },
          {
            "date": "2018-03-15",
            "count": 1
          },
          {
            "date": "2018-03-21",
            "count": 2
          },
          {
            "date": "2018-03-22",
            "count": 1
          },
          {
            "date": "2018-03-23",
            "count": 1
          },
          {
            "date": "2018-03-25",
            "count": 1
          },
          {
            "date": "2018-03-26",
            "count": 1
          },
          {
            "date": "2018-04-02",
            "count": 2
          },
          {
            "date": "2018-04-04",
            "count": 1
          },
          {
            "date": "2018-04-07",
            "count": 1
          },
          {
            "date": "2018-04-13",
            "count": 1
          },
          {
            "date": "2018-04-15",
            "count": 1
          },
          {
            "date": "2018-04-16",
            "count": 1
          },
          {
            "date": "2018-04-19",
            "count": 2
          },
          {
            "date": "2018-04-23",
            "count": 1
          },
          {
            "date": "2018-04-24",
            "count": 1
          },
          {
            "date": "2018-04-25",
            "count": 2
          },
          {
            "date": "2018-04-29",
            "count": 1
          },
          {
            "date": "2018-05-01",
            "count": 1
          },
          {
            "date": "2018-05-02",
            "count": 2
          },
          {
            "date": "2018-05-07",
            "count": 1
          },
          {
            "date": "2018-05-09",
            "count": 1
          },
          {
            "date": "2018-05-11",
            "count": 1
          },
          {
            "date": "2018-05-14",
            "count": 1
          },
          {
            "date": "2018-05-15",
            "count": 1
          },
          {
            "date": "2018-05-16",
            "count": 1
          },
          {
            "date": "2018-05-17",
            "count": 1
          },
          {
            "date": "2018-05-18",
            "count": 1
          },
          {
            "date": "2018-05-25",
            "count": 1
          },
          {
            "date": "2018-05-29",
            "count": 1
          },
          {
            "date": "2018-05-30",
            "count": 2
          },
          {
            "date": "2018-05-31",
            "count": 1
          },
          {
            "date": "2018-06-01",
            "count": 3
          },
          {
            "date": "2018-06-05",
            "count": 2
          },
          {
            "date": "2018-06-07",
            "count": 1
          },
          {
            "date": "2018-06-09",
            "count": 1
          },
          {
            "date": "2018-06-11",
            "count": 1
          },
          {
            "date": "2018-06-12",
            "count": 1
          },
          {
            "date": "2018-06-13",
            "count": 1
          },
          {
            "date": "2018-06-15",
            "count": 1
          },
          {
            "date": "2018-06-20",
            "count": 1
          },
          {
            "date": "2018-06-21",
            "count": 4
          },
          {
            "date": "2018-06-22",
            "count": 1
          },
          {
            "date": "2018-06-25",
            "count": 1
          },
          {
            "date": "2018-07-02",
            "count": 1
          },
          {
            "date": "2018-07-04",
            "count": 1
          },
          {
            "date": "2018-07-12",
            "count": 1
          },
          {
            "date": "2018-07-14",
            "count": 1
          },
          {
            "date": "2018-07-18",
            "count": 1
          },
          {
            "date": "2018-07-24",
            "count": 1
          },
          {
            "date": "2018-07-31",
            "count": 1
          },
          {
            "date": "2018-08-01",
            "count": 1
          },
          {
            "date": "2018-08-09",
            "count": 1
          },
          {
            "date": "2018-08-14",
            "count": 1
          },
          {
            "date": "2018-08-16",
            "count": 1
          },
          {
            "date": "2018-08-19",
            "count": 1
          },
          {
            "date": "2018-08-20",
            "count": 1
          },
          {
            "date": "2018-08-22",
            "count": 2
          },
          {
            "date": "2018-09-01",
            "count": 1
          },
          {
            "date": "2018-09-04",
            "count": 1
          },
          {
            "date": "2018-09-05",
            "count": 2
          },
          {
            "date": "2018-09-08",
            "count": 1
          },
          {
            "date": "2018-09-11",
            "count": 1
          },
          {
            "date": "2018-09-12",
            "count": 2
          },
          {
            "date": "2018-09-14",
            "count": 2
          },
          {
            "date": "2018-09-16",
            "count": 1
          },
          {
            "date": "2018-09-26",
            "count": 1
          },
          {
            "date": "2018-09-28",
            "count": 1
          },
          {
            "date": "2018-10-09",
            "count": 1
          },
          {
            "date": "2018-10-12",
            "count": 1
          },
          {
            "date": "2018-10-18",
            "count": 1
          },
          {
            "date": "2018-10-19",
            "count": 1
          },
          {
            "date": "2018-10-25",
            "count": 1
          },
          {
            "date": "2018-11-01",
            "count": 1
          },
          {
            "date": "2018-11-06",
            "count": 1
          },
          {
            "date": "2018-11-09",
            "count": 1
          },
          {
            "date": "2018-11-17",
            "count": 1
          },
          {
            "date": "2018-11-25",
            "count": 1
          },
          {
            "date": "2018-11-27",
            "count": 1
          },
          {
            "date": "2018-12-04",
            "count": 3
          },
          {
            "date": "2018-12-07",
            "count": 1
          },
          {
            "date": "2018-12-13",
            "count": 1
          },
          {
            "date": "2018-12-14",
            "count": 1
          },
          {
            "date": "2018-12-21",
            "count": 1
          },
          {
            "date": "2018-12-24",
            "count": 1
          },
          {
            "date": "2018-12-28",
            "count": 2
          },
          {
            "date": "2019-01-01",
            "count": 2
          },
          {
            "date": "2019-01-02",
            "count": 1
          },
          {
            "date": "2019-01-05",
            "count": 1
          },
          {
            "date": "2019-01-06",
            "count": 1
          },
          {
            "date": "2019-01-11",
            "count": 1
          },
          {
            "date": "2019-01-14",
            "count": 2
          },
          {
            "date": "2019-01-15",
            "count": 1
          },
          {
            "date": "2019-01-19",
            "count": 1
          },
          {
            "date": "2019-01-20",
            "count": 1
          },
          {
            "date": "2019-01-21",
            "count": 1
          },
          {
            "date": "2019-01-24",
            "count": 2
          },
          {
            "date": "2019-01-28",
            "count": 1
          },
          {
            "date": "2019-02-01",
            "count": 1
          },
          {
            "date": "2019-02-06",
            "count": 1
          },
          {
            "date": "2019-02-09",
            "count": 1
          },
          {
            "date": "2019-02-10",
            "count": 1
          },
          {
            "date": "2019-02-11",
            "count": 1
          },
          {
            "date": "2019-02-12",
            "count": 1
          },
          {
            "date": "2019-02-15",
            "count": 1
          },
          {
            "date": "2019-02-22",
            "count": 1
          },
          {
            "date": "2019-02-23",
            "count": 1
          },
          {
            "date": "2019-02-25",
            "count": 2
          },
          {
            "date": "2019-03-01",
            "count": 1
          },
          {
            "date": "2019-03-03",
            "count": 2
          },
          {
            "date": "2019-03-05",
            "count": 1
          },
          {
            "date": "2019-03-14",
            "count": 2
          },
          {
            "date": "2019-03-28",
            "count": 1
          },
          {
            "date": "2019-04-14",
            "count": 1
          },
          {
            "date": "2019-04-23",
            "count": 1
          },
          {
            "date": "2019-04-24",
            "count": 1
          },
          {
            "date": "2019-04-26",
            "count": 2
          },
          {
            "date": "2019-05-04",
            "count": 1
          },
          {
            "date": "2019-05-07",
            "count": 2
          },
          {
            "date": "2019-05-08",
            "count": 1
          },
          {
            "date": "2019-05-11",
            "count": 1
          },
          {
            "date": "2019-05-21",
            "count": 1
          },
          {
            "date": "2019-05-26",
            "count": 1
          },
          {
            "date": "2019-05-28",
            "count": 2
          },
          {
            "date": "2019-05-29",
            "count": 2
          },
          {
            "date": "2019-06-01",
            "count": 1
          },
          {
            "date": "2019-06-02",
            "count": 1
          },
          {
            "date": "2019-06-05",
            "count": 2
          },
          {
            "date": "2019-06-06",
            "count": 1
          },
          {
            "date": "2019-06-08",
            "count": 2
          },
          {
            "date": "2019-06-11",
            "count": 1
          },
          {
            "date": "2019-06-18",
            "count": 1
          },
          {
            "date": "2019-06-23",
            "count": 1
          },
          {
            "date": "2019-06-26",
            "count": 4
          },
          {
            "date": "2019-06-27",
            "count": 7
          },
          {
            "date": "2019-06-28",
            "count": 1
          },
          {
            "date": "2019-06-29",
            "count": 3
          },
          {
            "date": "2019-07-02",
            "count": 2
          },
          {
            "date": "2019-07-05",
            "count": 2
          },
          {
            "date": "2019-07-06",
            "count": 1
          },
          {
            "date": "2019-07-11",
            "count": 1
          },
          {
            "date": "2019-07-15",
            "count": 2
          },
          {
            "date": "2019-07-16",
            "count": 1
          },
          {
            "date": "2019-07-19",
            "count": 1
          },
          {
            "date": "2019-07-22",
            "count": 1
          },
          {
            "date": "2019-07-23",
            "count": 1
          },
          {
            "date": "2019-07-31",
            "count": 3
          },
          {
            "date": "2019-08-02",
            "count": 1
          },
          {
            "date": "2019-08-03",
            "count": 1
          },
          {
            "date": "2019-08-06",
            "count": 1
          },
          {
            "date": "2019-08-12",
            "count": 1
          },
          {
            "date": "2019-08-16",
            "count": 1
          },
          {
            "date": "2019-08-17",
            "count": 1
          },
          {
            "date": "2019-08-18",
            "count": 1
          },
          {
            "date": "2019-08-19",
            "count": 1
          },
          {
            "date": "2019-08-20",
            "count": 1
          },
          {
            "date": "2019-08-27",
            "count": 1
          },
          {
            "date": "2019-08-29",
            "count": 1
          },
          {
            "date": "2019-09-10",
            "count": 1
          },
          {
            "date": "2019-09-11",
            "count": 1
          },
          {
            "date": "2019-09-13",
            "count": 2
          },
          {
            "date": "2019-09-22",
            "count": 1
          },
          {
            "date": "2019-09-24",
            "count": 1
          },
          {
            "date": "2019-09-26",
            "count": 1
          },
          {
            "date": "2019-09-28",
            "count": 1
          },
          {
            "date": "2019-10-03",
            "count": 1
          },
          {
            "date": "2019-10-07",
            "count": 1
          },
          {
            "date": "2019-10-11",
            "count": 2
          },
          {
            "date": "2019-10-15",
            "count": 2
          },
          {
            "date": "2019-10-19",
            "count": 1
          },
          {
            "date": "2019-10-21",
            "count": 1
          },
          {
            "date": "2019-10-22",
            "count": 1
          },
          {
            "date": "2019-10-23",
            "count": 1
          },
          {
            "date": "2019-10-24",
            "count": 1
          },
          {
            "date": "2019-10-26",
            "count": 1
          },
          {
            "date": "2019-10-28",
            "count": 2
          },
          {
            "date": "2019-11-02",
            "count": 1
          },
          {
            "date": "2019-11-03",
            "count": 1
          },
          {
            "date": "2019-11-04",
            "count": 1
          },
          {
            "date": "2019-11-06",
            "count": 1
          },
          {
            "date": "2019-11-09",
            "count": 1
          },
          {
            "date": "2019-11-11",
            "count": 1
          },
          {
            "date": "2019-11-12",
            "count": 1
          },
          {
            "date": "2019-11-13",
            "count": 2
          },
          {
            "date": "2019-11-14",
            "count": 1
          },
          {
            "date": "2019-11-16",
            "count": 1
          },
          {
            "date": "2019-11-20",
            "count": 1
          },
          {
            "date": "2019-11-22",
            "count": 1
          },
          {
            "date": "2019-11-25",
            "count": 1
          },
          {
            "date": "2019-11-26",
            "count": 1
          },
          {
            "date": "2019-12-01",
            "count": 1
          },
          {
            "date": "2019-12-05",
            "count": 1
          },
          {
            "date": "2019-12-10",
            "count": 1
          },
          {
            "date": "2019-12-11",
            "count": 1
          },
          {
            "date": "2019-12-12",
            "count": 1
          },
          {
            "date": "2019-12-16",
            "count": 1
          },
          {
            "date": "2019-12-17",
            "count": 2
          },
          {
            "date": "2019-12-20",
            "count": 1
          },
          {
            "date": "2019-12-22",
            "count": 1
          },
          {
            "date": "2019-12-25",
            "count": 1
          },
          {
            "date": "2020-01-01",
            "count": 1
          },
          {
            "date": "2020-01-12",
            "count": 2
          },
          {
            "date": "2020-01-13",
            "count": 1
          },
          {
            "date": "2020-01-19",
            "count": 1
          },
          {
            "date": "2020-01-22",
            "count": 1
          },
          {
            "date": "2020-01-25",
            "count": 1
          },
          {
            "date": "2020-01-26",
            "count": 1
          },
          {
            "date": "2020-02-03",
            "count": 1
          },
          {
            "date": "2020-02-07",
            "count": 1
          },
          {
            "date": "2020-02-10",
            "count": 1
          },
          {
            "date": "2020-02-11",
            "count": 1
          },
          {
            "date": "2020-02-18",
            "count": 1
          },
          {
            "date": "2020-02-22",
            "count": 1
          },
          {
            "date": "2020-02-28",
            "count": 1
          },
          {
            "date": "2020-02-29",
            "count": 1
          },
          {
            "date": "2020-03-05",
            "count": 1
          },
          {
            "date": "2020-03-06",
            "count": 1
          },
          {
            "date": "2020-03-08",
            "count": 1
          },
          {
            "date": "2020-03-09",
            "count": 1
          },
          {
            "date": "2020-03-10",
            "count": 1
          },
          {
            "date": "2020-03-15",
            "count": 1
          },
          {
            "date": "2020-03-16",
            "count": 1
          },
          {
            "date": "2020-03-20",
            "count": 1
          },
          {
            "date": "2020-03-21",
            "count": 1
          },
          {
            "date": "2020-03-22",
            "count": 2
          },
          {
            "date": "2020-03-23",
            "count": 1
          },
          {
            "date": "2020-03-24",
            "count": 1
          },
          {
            "date": "2020-03-25",
            "count": 1
          },
          {
            "date": "2020-03-29",
            "count": 2
          },
          {
            "date": "2020-04-02",
            "count": 1
          },
          {
            "date": "2020-04-05",
            "count": 1
          },
          {
            "date": "2020-04-06",
            "count": 1
          },
          {
            "date": "2020-04-07",
            "count": 1
          },
          {
            "date": "2020-04-08",
            "count": 1
          },
          {
            "date": "2020-04-09",
            "count": 1
          },
          {
            "date": "2020-04-27",
            "count": 1
          },
          {
            "date": "2020-04-30",
            "count": 2
          },
          {
            "date": "2020-05-04",
            "count": 3
          },
          {
            "date": "2020-05-15",
            "count": 1
          },
          {
            "date": "2020-05-17",
            "count": 1
          },
          {
            "date": "2020-05-20",
            "count": 1
          },
          {
            "date": "2020-05-21",
            "count": 1
          },
          {
            "date": "2020-05-31",
            "count": 2
          },
          {
            "date": "2020-06-06",
            "count": 1
          },
          {
            "date": "2020-06-09",
            "count": 2
          },
          {
            "date": "2020-06-10",
            "count": 1
          },
          {
            "date": "2020-06-11",
            "count": 1
          },
          {
            "date": "2020-06-12",
            "count": 1
          },
          {
            "date": "2020-06-18",
            "count": 1
          },
          {
            "date": "2020-06-26",
            "count": 1
          },
          {
            "date": "2020-06-30",
            "count": 1
          },
          {
            "date": "2020-07-02",
            "count": 1
          },
          {
            "date": "2020-07-03",
            "count": 1
          },
          {
            "date": "2020-07-06",
            "count": 1
          },
          {
            "date": "2020-07-09",
            "count": 1
          },
          {
            "date": "2020-07-10",
            "count": 1
          },
          {
            "date": "2020-07-11",
            "count": 1
          },
          {
            "date": "2020-07-16",
            "count": 1
          },
          {
            "date": "2020-07-19",
            "count": 1
          },
          {
            "date": "2020-07-20",
            "count": 1
          },
          {
            "date": "2020-08-01",
            "count": 1
          },
          {
            "date": "2020-08-05",
            "count": 1
          },
          {
            "date": "2020-08-08",
            "count": 1
          },
          {
            "date": "2020-08-23",
            "count": 1
          },
          {
            "date": "2020-09-02",
            "count": 1
          },
          {
            "date": "2020-09-04",
            "count": 2
          },
          {
            "date": "2020-09-05",
            "count": 1
          },
          {
            "date": "2020-09-17",
            "count": 1
          },
          {
            "date": "2020-09-25",
            "count": 1
          },
          {
            "date": "2020-10-08",
            "count": 1
          },
          {
            "date": "2020-10-10",
            "count": 1
          },
          {
            "date": "2020-10-13",
            "count": 1
          },
          {
            "date": "2020-10-20",
            "count": 1
          },
          {
            "date": "2020-10-25",
            "count": 1
          },
          {
            "date": "2020-10-26",
            "count": 1
          },
          {
            "date": "2020-10-30",
            "count": 1
          },
          {
            "date": "2020-11-07",
            "count": 1
          },
          {
            "date": "2020-11-14",
            "count": 1
          },
          {
            "date": "2020-11-16",
            "count": 1
          },
          {
            "date": "2020-11-19",
            "count": 2
          },
          {
            "date": "2020-11-23",
            "count": 1
          },
          {
            "date": "2020-11-25",
            "count": 1
          },
          {
            "date": "2020-12-03",
            "count": 1
          },
          {
            "date": "2020-12-07",
            "count": 1
          },
          {
            "date": "2020-12-08",
            "count": 1
          },
          {
            "date": "2020-12-09",
            "count": 1
          },
          {
            "date": "2020-12-16",
            "count": 2
          },
          {
            "date": "2020-12-21",
            "count": 1
          },
          {
            "date": "2020-12-22",
            "count": 1
          },
          {
            "date": "2020-12-23",
            "count": 1
          },
          {
            "date": "2020-12-25",
            "count": 2
          },
          {
            "date": "2020-12-27",
            "count": 1
          },
          {
            "date": "2021-01-01",
            "count": 1
          },
          {
            "date": "2021-01-03",
            "count": 1
          },
          {
            "date": "2021-01-04",
            "count": 2
          },
          {
            "date": "2021-01-05",
            "count": 1
          },
          {
            "date": "2021-01-06",
            "count": 1
          },
          {
            "date": "2021-01-08",
            "count": 1
          },
          {
            "date": "2021-01-16",
            "count": 1
          },
          {
            "date": "2021-01-17",
            "count": 1
          },
          {
            "date": "2021-02-02",
            "count": 1
          },
          {
            "date": "2021-02-17",
            "count": 1
          },
          {
            "date": "2021-02-20",
            "count": 1
          },
          {
            "date": "2021-02-21",
            "count": 1
          },
          {
            "date": "2021-03-03",
            "count": 1
          },
          {
            "date": "2021-03-07",
            "count": 1
          },
          {
            "date": "2021-03-09",
            "count": 1
          },
          {
            "date": "2021-03-11",
            "count": 1
          },
          {
            "date": "2021-03-13",
            "count": 1
          },
          {
            "date": "2021-03-16",
            "count": 2
          },
          {
            "date": "2021-03-17",
            "count": 1
          },
          {
            "date": "2021-03-24",
            "count": 1
          },
          {
            "date": "2021-04-07",
            "count": 1
          },
          {
            "date": "2021-04-16",
            "count": 1
          },
          {
            "date": "2021-04-19",
            "count": 1
          },
          {
            "date": "2021-04-23",
            "count": 1
          },
          {
            "date": "2021-04-25",
            "count": 1
          },
          {
            "date": "2021-04-26",
            "count": 1
          },
          {
            "date": "2021-05-06",
            "count": 1
          },
          {
            "date": "2021-05-09",
            "count": 1
          },
          {
            "date": "2021-05-10",
            "count": 1
          },
          {
            "date": "2021-05-18",
            "count": 1
          },
          {
            "date": "2021-05-19",
            "count": 1
          },
          {
            "date": "2021-05-20",
            "count": 1
          },
          {
            "date": "2021-05-22",
            "count": 1
          },
          {
            "date": "2021-05-23",
            "count": 1
          },
          {
            "date": "2021-06-03",
            "count": 1
          },
          {
            "date": "2021-06-08",
            "count": 1
          },
          {
            "date": "2021-06-16",
            "count": 2
          },
          {
            "date": "2021-06-30",
            "count": 1
          },
          {
            "date": "2021-07-01",
            "count": 1
          },
          {
            "date": "2021-07-02",
            "count": 2
          },
          {
            "date": "2021-07-16",
            "count": 1
          },
          {
            "date": "2021-07-25",
            "count": 1
          },
          {
            "date": "2021-07-30",
            "count": 1
          },
          {
            "date": "2021-08-03",
            "count": 1
          },
          {
            "date": "2021-08-05",
            "count": 2
          },
          {
            "date": "2021-08-10",
            "count": 2
          },
          {
            "date": "2021-08-18",
            "count": 1
          },
          {
            "date": "2021-08-27",
            "count": 1
          },
          {
            "date": "2021-08-31",
            "count": 1
          },
          {
            "date": "2021-09-04",
            "count": 1
          },
          {
            "date": "2021-09-06",
            "count": 1
          },
          {
            "date": "2021-09-09",
            "count": 1
          },
          {
            "date": "2021-09-28",
            "count": 1
          },
          {
            "date": "2021-10-07",
            "count": 1
          },
          {
            "date": "2021-10-14",
            "count": 1
          },
          {
            "date": "2021-10-21",
            "count": 1
          },
          {
            "date": "2021-10-22",
            "count": 1
          },
          {
            "date": "2021-10-26",
            "count": 1
          },
          {
            "date": "2021-10-28",
            "count": 1
          },
          {
            "date": "2021-11-02",
            "count": 1
          },
          {
            "date": "2021-11-18",
            "count": 13
          },
          {
            "date": "2021-11-19",
            "count": 6
          },
          {
            "date": "2021-11-20",
            "count": 4
          },
          {
            "date": "2021-11-21",
            "count": 1
          },
          {
            "date": "2021-11-22",
            "count": 3
          },
          {
            "date": "2021-11-23",
            "count": 4
          },
          {
            "date": "2021-11-24",
            "count": 1
          },
          {
            "date": "2021-11-26",
            "count": 1
          },
          {
            "date": "2021-12-02",
            "count": 1
          },
          {
            "date": "2021-12-04",
            "count": 1
          },
          {
            "date": "2021-12-06",
            "count": 2
          },
          {
            "date": "2021-12-14",
            "count": 1
          },
          {
            "date": "2021-12-15",
            "count": 1
          },
          {
            "date": "2021-12-21",
            "count": 1
          },
          {
            "date": "2021-12-25",
            "count": 1
          },
          {
            "date": "2022-01-03",
            "count": 2
          },
          {
            "date": "2022-01-12",
            "count": 1
          },
          {
            "date": "2022-01-13",
            "count": 1
          },
          {
            "date": "2022-01-16",
            "count": 1
          },
          {
            "date": "2022-01-18",
            "count": 1
          },
          {
            "date": "2022-01-19",
            "count": 1
          },
          {
            "date": "2022-01-22",
            "count": 1
          },
          {
            "date": "2022-01-23",
            "count": 1
          },
          {
            "date": "2022-01-24",
            "count": 1
          },
          {
            "date": "2022-02-02",
            "count": 1
          },
          {
            "date": "2022-02-07",
            "count": 1
          },
          {
            "date": "2022-02-11",
            "count": 2
          },
          {
            "date": "2022-02-12",
            "count": 1
          },
          {
            "date": "2022-02-15",
            "count": 1
          },
          {
            "date": "2022-02-21",
            "count": 1
          },
          {
            "date": "2022-02-22",
            "count": 2
          },
          {
            "date": "2022-02-23",
            "count": 1
          },
          {
            "date": "2022-03-06",
            "count": 1
          },
          {
            "date": "2022-03-10",
            "count": 2
          },
          {
            "date": "2022-03-15",
            "count": 1
          },
          {
            "date": "2022-03-25",
            "count": 2
          },
          {
            "date": "2022-04-08",
            "count": 1
          },
          {
            "date": "2022-04-17",
            "count": 3
          },
          {
            "date": "2022-04-20",
            "count": 1
          },
          {
            "date": "2022-04-21",
            "count": 1
          },
          {
            "date": "2022-04-24",
            "count": 1
          },
          {
            "date": "2022-04-27",
            "count": 1
          },
          {
            "date": "2022-04-28",
            "count": 1
          },
          {
            "date": "2022-05-05",
            "count": 1
          },
          {
            "date": "2022-05-12",
            "count": 5
          },
          {
            "date": "2022-05-13",
            "count": 4
          },
          {
            "date": "2022-05-14",
            "count": 2
          },
          {
            "date": "2022-05-15",
            "count": 1
          },
          {
            "date": "2022-05-16",
            "count": 1
          },
          {
            "date": "2022-05-19",
            "count": 1
          },
          {
            "date": "2022-05-20",
            "count": 1
          },
          {
            "date": "2022-05-24",
            "count": 1
          },
          {
            "date": "2022-05-27",
            "count": 1
          },
          {
            "date": "2022-05-28",
            "count": 1
          },
          {
            "date": "2022-06-01",
            "count": 2
          },
          {
            "date": "2022-06-05",
            "count": 1
          },
          {
            "date": "2022-06-08",
            "count": 1
          },
          {
            "date": "2022-06-10",
            "count": 1
          },
          {
            "date": "2022-06-13",
            "count": 1
          },
          {
            "date": "2022-06-25",
            "count": 2
          },
          {
            "date": "2022-07-06",
            "count": 2
          },
          {
            "date": "2022-07-13",
            "count": 1
          },
          {
            "date": "2022-07-19",
            "count": 1
          },
          {
            "date": "2022-07-22",
            "count": 1
          },
          {
            "date": "2022-07-31",
            "count": 1
          },
          {
            "date": "2022-08-01",
            "count": 1
          },
          {
            "date": "2022-08-02",
            "count": 1
          },
          {
            "date": "2022-08-08",
            "count": 1
          },
          {
            "date": "2022-08-10",
            "count": 1
          },
          {
            "date": "2022-08-11",
            "count": 1
          },
          {
            "date": "2022-08-21",
            "count": 1
          },
          {
            "date": "2022-08-22",
            "count": 1
          },
          {
            "date": "2022-08-26",
            "count": 1
          },
          {
            "date": "2022-08-31",
            "count": 1
          },
          {
            "date": "2022-09-02",
            "count": 1
          },
          {
            "date": "2022-09-05",
            "count": 1
          },
          {
            "date": "2022-09-07",
            "count": 1
          },
          {
            "date": "2022-09-11",
            "count": 1
          },
          {
            "date": "2022-09-22",
            "count": 2
          },
          {
            "date": "2022-10-09",
            "count": 1
          },
          {
            "date": "2022-10-11",
            "count": 1
          },
          {
            "date": "2022-10-12",
            "count": 1
          },
          {
            "date": "2022-10-17",
            "count": 1
          },
          {
            "date": "2022-11-03",
            "count": 1
          },
          {
            "date": "2022-11-08",
            "count": 1
          },
          {
            "date": "2022-11-09",
            "count": 1
          },
          {
            "date": "2022-11-11",
            "count": 2
          },
          {
            "date": "2022-11-16",
            "count": 1
          },
          {
            "date": "2022-11-19",
            "count": 1
          },
          {
            "date": "2022-12-05",
            "count": 1
          },
          {
            "date": "2022-12-09",
            "count": 1
          },
          {
            "date": "2022-12-11",
            "count": 1
          },
          {
            "date": "2022-12-17",
            "count": 1
          },
          {
            "date": "2022-12-19",
            "count": 1
          },
          {
            "date": "2022-12-20",
            "count": 1
          },
          {
            "date": "2022-12-27",
            "count": 1
          },
          {
            "date": "2022-12-28",
            "count": 1
          },
          {
            "date": "2023-01-04",
            "count": 1
          },
          {
            "date": "2023-01-05",
            "count": 1
          },
          {
            "date": "2023-01-09",
            "count": 1
          },
          {
            "date": "2023-01-10",
            "count": 2
          },
          {
            "date": "2023-01-17",
            "count": 2
          },
          {
            "date": "2023-01-20",
            "count": 1
          },
          {
            "date": "2023-01-22",
            "count": 1
          },
          {
            "date": "2023-02-03",
            "count": 1
          },
          {
            "date": "2023-02-09",
            "count": 1
          },
          {
            "date": "2023-02-10",
            "count": 1
          },
          {
            "date": "2023-02-13",
            "count": 4
          },
          {
            "date": "2023-02-18",
            "count": 1
          },
          {
            "date": "2023-02-21",
            "count": 1
          },
          {
            "date": "2023-03-02",
            "count": 1
          },
          {
            "date": "2023-03-07",
            "count": 1
          },
          {
            "date": "2023-03-10",
            "count": 1
          },
          {
            "date": "2023-03-11",
            "count": 1
          },
          {
            "date": "2023-03-12",
            "count": 1
          },
          {
            "date": "2023-03-13",
            "count": 2
          },
          {
            "date": "2023-03-14",
            "count": 2
          },
          {
            "date": "2023-03-16",
            "count": 1
          },
          {
            "date": "2023-03-17",
            "count": 1
          },
          {
            "date": "2023-03-27",
            "count": 1
          },
          {
            "date": "2023-03-29",
            "count": 1
          },
          {
            "date": "2023-04-08",
            "count": 1
          },
          {
            "date": "2023-04-09",
            "count": 1
          },
          {
            "date": "2023-04-10",
            "count": 1
          },
          {
            "date": "2023-04-12",
            "count": 3
          },
          {
            "date": "2023-04-17",
            "count": 1
          },
          {
            "date": "2023-04-18",
            "count": 1
          },
          {
            "date": "2023-05-03",
            "count": 2
          },
          {
            "date": "2023-05-10",
            "count": 2
          },
          {
            "date": "2023-05-11",
            "count": 1
          },
          {
            "date": "2023-05-12",
            "count": 1
          },
          {
            "date": "2023-05-15",
            "count": 1
          },
          {
            "date": "2023-05-17",
            "count": 1
          },
          {
            "date": "2023-05-21",
            "count": 1
          },
          {
            "date": "2023-05-24",
            "count": 3
          },
          {
            "date": "2023-05-31",
            "count": 1
          },
          {
            "date": "2023-06-02",
            "count": 1
          },
          {
            "date": "2023-06-07",
            "count": 1
          },
          {
            "date": "2023-06-16",
            "count": 1
          },
          {
            "date": "2023-06-19",
            "count": 1
          },
          {
            "date": "2023-06-22",
            "count": 1
          },
          {
            "date": "2023-06-27",
            "count": 1
          },
          {
            "date": "2023-07-06",
            "count": 1
          },
          {
            "date": "2023-07-09",
            "count": 1
          },
          {
            "date": "2023-07-14",
            "count": 1
          },
          {
            "date": "2023-07-15",
            "count": 1
          },
          {
            "date": "2023-07-17",
            "count": 1
          },
          {
            "date": "2023-07-19",
            "count": 1
          },
          {
            "date": "2023-07-23",
            "count": 1
          },
          {
            "date": "2023-07-28",
            "count": 1
          },
          {
            "date": "2023-07-31",
            "count": 1
          },
          {
            "date": "2023-08-04",
            "count": 1
          },
          {
            "date": "2023-08-06",
            "count": 1
          },
          {
            "date": "2023-08-24",
            "count": 1
          },
          {
            "date": "2023-08-29",
            "count": 1
          },
          {
            "date": "2023-08-30",
            "count": 4
          },
          {
            "date": "2023-09-06",
            "count": 2
          },
          {
            "date": "2023-09-09",
            "count": 1
          },
          {
            "date": "2023-09-26",
            "count": 1
          },
          {
            "date": "2023-10-05",
            "count": 1
          },
          {
            "date": "2023-10-07",
            "count": 1
          },
          {
            "date": "2023-10-08",
            "count": 1
          },
          {
            "date": "2023-10-12",
            "count": 1
          },
          {
            "date": "2023-10-18",
            "count": 1
          },
          {
            "date": "2023-10-20",
            "count": 1
          },
          {
            "date": "2023-10-27",
            "count": 1
          },
          {
            "date": "2023-10-30",
            "count": 2
          },
          {
            "date": "2023-11-01",
            "count": 2
          },
          {
            "date": "2023-11-06",
            "count": 1
          },
          {
            "date": "2023-11-09",
            "count": 1
          },
          {
            "date": "2023-11-11",
            "count": 1
          },
          {
            "date": "2023-11-22",
            "count": 1
          },
          {
            "date": "2023-11-28",
            "count": 1
          },
          {
            "date": "2023-11-29",
            "count": 1
          },
          {
            "date": "2023-12-04",
            "count": 3
          },
          {
            "date": "2023-12-12",
            "count": 1
          },
          {
            "date": "2023-12-13",
            "count": 1
          },
          {
            "date": "2023-12-15",
            "count": 1
          },
          {
            "date": "2023-12-16",
            "count": 1
          },
          {
            "date": "2023-12-18",
            "count": 1
          },
          {
            "date": "2023-12-23",
            "count": 1
          },
          {
            "date": "2023-12-24",
            "count": 2
          },
          {
            "date": "2024-01-06",
            "count": 1
          },
          {
            "date": "2024-01-10",
            "count": 1
          },
          {
            "date": "2024-01-14",
            "count": 1
          },
          {
            "date": "2024-01-17",
            "count": 1
          },
          {
            "date": "2024-01-19",
            "count": 1
          },
          {
            "date": "2024-01-22",
            "count": 1
          },
          {
            "date": "2024-01-24",
            "count": 1
          },
          {
            "date": "2024-01-30",
            "count": 1
          },
          {
            "date": "2024-02-03",
            "count": 1
          },
          {
            "date": "2024-02-12",
            "count": 1
          },
          {
            "date": "2024-02-13",
            "count": 1
          },
          {
            "date": "2024-02-14",
            "count": 1
          },
          {
            "date": "2024-02-15",
            "count": 1
          },
          {
            "date": "2024-02-16",
            "count": 1
          },
          {
            "date": "2024-03-02",
            "count": 1
          },
          {
            "date": "2024-03-03",
            "count": 1
          },
          {
            "date": "2024-03-04",
            "count": 1
          },
          {
            "date": "2024-03-06",
            "count": 2
          },
          {
            "date": "2024-03-07",
            "count": 2
          },
          {
            "date": "2024-03-11",
            "count": 1
          },
          {
            "date": "2024-03-17",
            "count": 1
          },
          {
            "date": "2024-03-18",
            "count": 1
          },
          {
            "date": "2024-03-23",
            "count": 1
          },
          {
            "date": "2024-04-17",
            "count": 1
          },
          {
            "date": "2024-04-22",
            "count": 1
          },
          {
            "date": "2024-04-30",
            "count": 1
          },
          {
            "date": "2024-05-03",
            "count": 2
          },
          {
            "date": "2024-05-13",
            "count": 1
          },
          {
            "date": "2024-05-14",
            "count": 1
          },
          {
            "date": "2024-05-21",
            "count": 1
          },
          {
            "date": "2024-05-23",
            "count": 1
          },
          {
            "date": "2024-05-30",
            "count": 1
          },
          {
            "date": "2024-06-02",
            "count": 1
          },
          {
            "date": "2024-06-05",
            "count": 1
          },
          {
            "date": "2024-06-06",
            "count": 1
          },
          {
            "date": "2024-06-13",
            "count": 1
          },
          {
            "date": "2024-06-14",
            "count": 1
          },
          {
            "date": "2024-06-19",
            "count": 1
          },
          {
            "date": "2024-07-06",
            "count": 1
          },
          {
            "date": "2024-07-11",
            "count": 1
          },
          {
            "date": "2024-07-18",
            "count": 1
          },
          {
            "date": "2024-07-19",
            "count": 2
          },
          {
            "date": "2024-07-21",
            "count": 1
          },
          {
            "date": "2024-07-23",
            "count": 1
          },
          {
            "date": "2024-07-30",
            "count": 2
          },
          {
            "date": "2024-08-05",
            "count": 1
          },
          {
            "date": "2024-08-13",
            "count": 1
          },
          {
            "date": "2024-08-14",
            "count": 1
          },
          {
            "date": "2024-08-19",
            "count": 1
          },
          {
            "date": "2024-08-20",
            "count": 1
          },
          {
            "date": "2024-08-21",
            "count": 1
          },
          {
            "date": "2024-08-25",
            "count": 1
          },
          {
            "date": "2024-08-27",
            "count": 1
          },
          {
            "date": "2024-09-03",
            "count": 2
          },
          {
            "date": "2024-09-08",
            "count": 1
          },
          {
            "date": "2024-09-12",
            "count": 1
          },
          {
            "date": "2024-09-16",
            "count": 1
          },
          {
            "date": "2024-09-19",
            "count": 1
          },
          {
            "date": "2024-09-24",
            "count": 1
          },
          {
            "date": "2024-09-25",
            "count": 1
          },
          {
            "date": "2024-10-02",
            "count": 1
          },
          {
            "date": "2024-10-05",
            "count": 1
          },
          {
            "date": "2024-10-09",
            "count": 1
          },
          {
            "date": "2024-10-10",
            "count": 1
          },
          {
            "date": "2024-10-19",
            "count": 1
          },
          {
            "date": "2024-10-23",
            "count": 1
          },
          {
            "date": "2024-10-28",
            "count": 2
          },
          {
            "date": "2024-11-01",
            "count": 2
          },
          {
            "date": "2024-11-02",
            "count": 1
          },
          {
            "date": "2024-11-03",
            "count": 1
          },
          {
            "date": "2024-11-07",
            "count": 1
          },
          {
            "date": "2024-11-16",
            "count": 1
          },
          {
            "date": "2024-11-20",
            "count": 1
          },
          {
            "date": "2024-11-24",
            "count": 1
          },
          {
            "date": "2024-11-27",
            "count": 1
          },
          {
            "date": "2024-11-29",
            "count": 1
          },
          {
            "date": "2024-12-02",
            "count": 1
          },
          {
            "date": "2024-12-04",
            "count": 1
          },
          {
            "date": "2024-12-12",
            "count": 1
          },
          {
            "date": "2024-12-16",
            "count": 1
          },
          {
            "date": "2024-12-20",
            "count": 1
          },
          {
            "date": "2024-12-31",
            "count": 1
          },
          {
            "date": "2025-01-01",
            "count": 1
          },
          {
            "date": "2025-01-02",
            "count": 1
          },
          {
            "date": "2025-01-07",
            "count": 1
          },
          {
            "date": "2025-01-08",
            "count": 1
          },
          {
            "date": "2025-01-10",
            "count": 1
          },
          {
            "date": "2025-01-14",
            "count": 1
          },
          {
            "date": "2025-01-15",
            "count": 2
          },
          {
            "date": "2025-01-28",
            "count": 1
          },
          {
            "date": "2025-01-30",
            "count": 1
          },
          {
            "date": "2025-02-11",
            "count": 1
          },
          {
            "date": "2025-02-17",
            "count": 1
          },
          {
            "date": "2025-02-19",
            "count": 2
          },
          {
            "date": "2025-02-24",
            "count": 1
          },
          {
            "date": "2025-02-28",
            "count": 1
          },
          {
            "date": "2025-03-04",
            "count": 1
          },
          {
            "date": "2025-03-05",
            "count": 1
          },
          {
            "date": "2025-03-06",
            "count": 2
          },
          {
            "date": "2025-03-13",
            "count": 1
          },
          {
            "date": "2025-03-24",
            "count": 1
          },
          {
            "date": "2025-03-27",
            "count": 1
          },
          {
            "date": "2025-04-04",
            "count": 1
          },
          {
            "date": "2025-04-06",
            "count": 1
          },
          {
            "date": "2025-04-08",
            "count": 1
          },
          {
            "date": "2025-04-16",
            "count": 1
          },
          {
            "date": "2025-04-22",
            "count": 2
          },
          {
            "date": "2025-05-08",
            "count": 1
          },
          {
            "date": "2025-05-14",
            "count": 1
          },
          {
            "date": "2025-05-15",
            "count": 1
          },
          {
            "date": "2025-05-16",
            "count": 2
          },
          {
            "date": "2025-05-17",
            "count": 1
          },
          {
            "date": "2025-05-22",
            "count": 1
          },
          {
            "date": "2025-06-01",
            "count": 1
          },
          {
            "date": "2025-06-04",
            "count": 1
          },
          {
            "date": "2025-06-06",
            "count": 1
          },
          {
            "date": "2025-06-10",
            "count": 1
          },
          {
            "date": "2025-06-11",
            "count": 1
          },
          {
            "date": "2025-06-14",
            "count": 1
          },
          {
            "date": "2025-06-19",
            "count": 2
          },
          {
            "date": "2025-06-20",
            "count": 1
          },
          {
            "date": "2025-06-25",
            "count": 1
          },
          {
            "date": "2025-06-29",
            "count": 1
          },
          {
            "date": "2025-06-30",
            "count": 1
          },
          {
            "date": "2025-07-11",
            "count": 1
          },
          {
            "date": "2025-07-15",
            "count": 1
          },
          {
            "date": "2025-07-23",
            "count": 1
          },
          {
            "date": "2025-07-31",
            "count": 2
          },
          {
            "date": "2025-08-01",
            "count": 1
          },
          {
            "date": "2025-08-12",
            "count": 2
          },
          {
            "date": "2025-08-14",
            "count": 1
          },
          {
            "date": "2025-08-29",
            "count": 2
          },
          {
            "date": "2025-09-04",
            "count": 1
          },
          {
            "date": "2025-09-06",
            "count": 1
          },
          {
            "date": "2025-09-15",
            "count": 1
          },
          {
            "date": "2025-09-18",
            "count": 1
          },
          {
            "date": "2025-09-19",
            "count": 1
          },
          {
            "date": "2025-09-21",
            "count": 1
          },
          {
            "date": "2025-10-09",
            "count": 1
          },
          {
            "date": "2025-11-09",
            "count": 1
          },
          {
            "date": "2025-12-02",
            "count": 1
          },
          {
            "date": "2025-12-07",
            "count": 1
          },
          {
            "date": "2025-12-10",
            "count": 2
          },
          {
            "date": "2025-12-20",
            "count": 1
          },
          {
            "date": "2025-12-23",
            "count": 1
          },
          {
            "date": "2026-01-04",
            "count": 1
          },
          {
            "date": "2026-01-14",
            "count": 1
          },
          {
            "date": "2026-01-16",
            "count": 2
          },
          {
            "date": "2026-01-20",
            "count": 1
          },
          {
            "date": "2026-01-28",
            "count": 1
          },
          {
            "date": "2026-02-01",
            "count": 1
          },
          {
            "date": "2026-02-03",
            "count": 2
          },
          {
            "date": "2026-02-05",
            "count": 1
          },
          {
            "date": "2026-02-13",
            "count": 1
          },
          {
            "date": "2026-03-10",
            "count": 1
          },
          {
            "date": "2026-03-26",
            "count": 1
          },
          {
            "date": "2026-03-28",
            "count": 1
          },
          {
            "date": "2026-04-12",
            "count": 1
          },
          {
            "date": "2026-04-15",
            "count": 2
          },
          {
            "date": "2026-04-17",
            "count": 1
          },
          {
            "date": "2026-05-01",
            "count": 1
          },
          {
            "date": "2026-05-19",
            "count": 1
          },
          {
            "date": "2026-05-23",
            "count": 1
          },
          {
            "date": "2026-05-24",
            "count": 1
          },
          {
            "date": "2026-05-25",
            "count": 7
          },
          {
            "date": "2026-05-30",
            "count": 1
          },
          {
            "date": "2026-06-13",
            "count": 1
          },
          {
            "date": "2026-06-24",
            "count": 1
          },
          {
            "date": "2026-06-29",
            "count": 1
          },
          {
            "date": "2026-07-09",
            "count": 1
          },
          {
            "date": "2026-07-11",
            "count": 1
          },
          {
            "date": "2026-07-14",
            "count": 1
          },
          {
            "date": "2026-07-21",
            "count": 1
          }
        ],
        "complete": false,
        "collected": 1000,
        "total_stars": 1925
      },
      "open_issues_and_prs": 65
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 63485,
      "source_files_sampled": 133,
      "oversized_source_files": 1,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "Gemfile"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 2,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 13,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "rubygems"
      ],
      "dependencies": [
        {
          "name": "sorbet",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": "0.6.12872"
        },
        {
          "name": "tapioca",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": "0.17.10"
        },
        {
          "name": "spoom",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rbs-inline",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "webrick",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "rbs-inline",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "sorbet",
            "direct": true,
            "version": "0.6.12872",
            "ecosystem": "rubygems"
          },
          {
            "name": "spoom",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "tapioca",
            "direct": true,
            "version": "0.17.10",
            "ecosystem": "rubygems"
          },
          {
            "name": "webrick",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "afm",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "cane",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "hashery",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "morecane",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "pry",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rake",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rdoc",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rspec",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "ruby-rc4",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "ttfunk",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 15,
        "direct_count": 5,
        "indirect_count": 10
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 4,
        "merged_prs": 282,
        "open_issues": 61,
        "closed_ratio": 0.767,
        "closed_issues": 201,
        "closed_unmerged_prs": 57
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "yob",
          "commits": 1481,
          "avatar_url": "https://avatars.githubusercontent.com/u/8132?v=4"
        },
        {
          "type": "User",
          "login": "sebbASF",
          "commits": 28,
          "avatar_url": "https://avatars.githubusercontent.com/u/16689231?v=4"
        },
        {
          "type": "User",
          "login": "bernerdschaefer",
          "commits": 22,
          "avatar_url": "https://avatars.githubusercontent.com/u/193?v=4"
        },
        {
          "type": "User",
          "login": "alexdowad",
          "commits": 12,
          "avatar_url": "https://avatars.githubusercontent.com/u/1067359?v=4"
        },
        {
          "type": "User",
          "login": "3jb",
          "commits": 12,
          "avatar_url": "https://avatars.githubusercontent.com/u/784728?v=4"
        },
        {
          "type": "User",
          "login": "gyuchang",
          "commits": 9,
          "avatar_url": "https://avatars.githubusercontent.com/u/813607?v=4"
        },
        {
          "type": "User",
          "login": "sbilharz",
          "commits": 9,
          "avatar_url": "https://avatars.githubusercontent.com/u/11405612?v=4"
        },
        {
          "type": "User",
          "login": "tardate",
          "commits": 5,
          "avatar_url": "https://avatars.githubusercontent.com/u/16432?v=4"
        },
        {
          "type": "User",
          "login": "koriroys",
          "commits": 5,
          "avatar_url": "https://avatars.githubusercontent.com/u/1118323?v=4"
        },
        {
          "type": "User",
          "login": "amatsuda",
          "commits": 5,
          "avatar_url": "https://avatars.githubusercontent.com/u/11493?v=4"
        }
      ],
      "contributors_sampled": 61,
      "top_contributor_share": 0.893
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": true,
      "ci_workflows": [],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 8,
            "reason": "8 out of 9 merged PRs checked by a CI test -- score normalized to 8",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 1/11 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 26 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "578db3d49b9cfc458b186915896ae29f62ccd126",
        "ran_at": "2026-07-21T23:33:27Z",
        "aggregate_score": 3.9,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-15T02:30:48Z",
      "oldest_open_prs": [
        {
          "number": 209,
          "created_at": "2017-03-13T01:21:23Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 301,
          "created_at": "2019-10-18T04:44:28Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 326,
          "created_at": "2020-01-31T09:41:40Z",
          "last_comment_at": "2020-02-26T08:00:05Z",
          "last_comment_author": "bwl21"
        },
        {
          "number": 524,
          "created_at": "2023-10-25T20:11:29Z",
          "last_comment_at": "2025-03-13T08:19:15Z",
          "last_comment_author": "rgarner"
        }
      ],
      "last_merged_pr_at": "2026-07-15T02:30:47Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": [
        {
          "number": 45,
          "created_at": "2012-02-06T00:30:45Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 55,
          "created_at": "2012-05-24T21:30:59Z",
          "last_comment_at": "2012-06-11T19:30:02Z",
          "last_comment_author": "andrewajo"
        },
        {
          "number": 72,
          "created_at": "2013-01-01T17:45:39Z",
          "last_comment_at": "2014-04-24T03:39:02Z",
          "last_comment_author": "zachary-wq"
        },
        {
          "number": 76,
          "created_at": "2013-01-18T06:12:44Z",
          "last_comment_at": "2013-02-25T14:24:59Z",
          "last_comment_author": "sandsfish"
        },
        {
          "number": 84,
          "created_at": "2013-02-16T15:30:01Z",
          "last_comment_at": "2013-02-26T04:03:50Z",
          "last_comment_author": "utensil"
        },
        {
          "number": 93,
          "created_at": "2013-04-10T11:33:02Z",
          "last_comment_at": "2013-04-10T16:37:07Z",
          "last_comment_author": "dpzaba"
        },
        {
          "number": 100,
          "created_at": "2013-05-09T11:17:50Z",
          "last_comment_at": "2013-05-13T07:39:01Z",
          "last_comment_author": "yob"
        },
        {
          "number": 114,
          "created_at": "2013-10-06T11:23:27Z",
          "last_comment_at": "2020-01-12T15:30:03Z",
          "last_comment_author": "toy"
        },
        {
          "number": 115,
          "created_at": "2013-10-27T11:26:06Z",
          "last_comment_at": "2013-10-27T21:05:37Z",
          "last_comment_author": "mejibyte"
        },
        {
          "number": 118,
          "created_at": "2014-01-07T18:17:47Z",
          "last_comment_at": "2017-02-14T14:01:16Z",
          "last_comment_author": "yob"
        },
        {
          "number": 119,
          "created_at": "2014-02-03T01:47:25Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 127,
          "created_at": "2014-05-05T05:45:04Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 132,
          "created_at": "2014-06-21T20:38:48Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 137,
          "created_at": "2014-12-04T18:38:10Z",
          "last_comment_at": "2021-10-17T21:39:50Z",
          "last_comment_author": "sebbASF"
        },
        {
          "number": 170,
          "created_at": "2016-03-18T13:31:06Z",
          "last_comment_at": "2017-02-14T13:47:23Z",
          "last_comment_author": "yob"
        },
        {
          "number": 205,
          "created_at": "2017-03-05T19:31:37Z",
          "last_comment_at": "2017-03-05T22:29:06Z",
          "last_comment_author": "yob"
        },
        {
          "number": 214,
          "created_at": "2017-04-03T12:50:04Z",
          "last_comment_at": "2022-01-29T23:49:17Z",
          "last_comment_author": "yob"
        },
        {
          "number": 216,
          "created_at": "2017-05-02T12:53:37Z",
          "last_comment_at": "2022-01-13T00:02:38Z",
          "last_comment_author": "yob"
        },
        {
          "number": 260,
          "created_at": "2017-11-11T19:02:46Z",
          "last_comment_at": "2019-10-26T12:09:56Z",
          "last_comment_author": "yob"
        },
        {
          "number": 272,
          "created_at": "2018-02-03T22:20:43Z",
          "last_comment_at": "2019-03-26T02:54:08Z",
          "last_comment_author": "rockorequin"
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/yob/pdf-reader",
    "host": "github.com",
    "name": "pdf-reader",
    "owner": "yob"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 59,
      "inputs": {
        "security": 51,
        "vitality": 64,
        "community": 76,
        "governance": 62,
        "engineering": 40
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "moderate",
        "name": "Vitality",
        "value": 64,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 74,
            "inputs": {
              "commits_last_year": 121,
              "human_commit_share": 1,
              "days_since_last_push": 6,
              "active_weeks_last_year": 15
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 6 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "15/52 weeks with commits",
                "points": 10.4,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 15
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "121 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 121
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "moderate",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 50,
            "inputs": {
              "releases_count": 64,
              "latest_release_tag": "v2.15.1",
              "releases_from_tags": true,
              "days_since_latest_release": 205,
              "mean_days_between_releases": 158.1
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "64 version tags (no GitHub releases)",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "version_tags_no_releases",
                    "params": {
                      "count": 64
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 205 days ago",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 205
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~158.1 days",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 158.1
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 6,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 6 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "good",
        "name": "Community & Adoption",
        "value": 76,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "good",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 83,
            "inputs": {
              "forks": 284,
              "stars": 1925,
              "watchers": 46,
              "growth_state": "organic",
              "growth_factor_pct": 100
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "1,925 stars",
                "points": 53.3,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 1925
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "284 forks",
                "points": 20.4,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 284
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "46 watchers",
                "points": 9.2,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 46
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "excellent",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "packages": [
                "pdf-reader"
              ],
              "dependents": null,
              "ecosystems": "rubygems",
              "total_downloads": 109562630,
              "monthly_downloads": null
            },
            "components": [
              {
                "key": "total_downloads",
                "name": "Total downloads",
                "detail": "109,562,630 downloads all-time across rubygems",
                "points": 80,
                "status": "met",
                "details": [
                  {
                    "code": "downloads_total",
                    "params": {
                      "count": 109562630,
                      "ecosystems": "rubygems"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 62,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 35,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 61,
              "top_contributor_share": 0.893
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 89% of commits",
                "points": 2.4,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 89
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "61 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 61
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 26 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "moderate",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "merged_prs": 282,
              "open_issues": 61,
              "closed_issues": 201,
              "issue_closed_ratio": 0.767,
              "closed_unmerged_prs": 57
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "77% of issues closed",
                "points": 35.9,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 77
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "282/339 decided PRs merged",
                "points": 31.8,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 282,
                      "decided": 339
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 1/11 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 65,
            "inputs": {
              "followers": 236,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "yob",
              "public_repos": 143,
              "account_age_days": 6664
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "236 followers of yob",
                "points": 17.1,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 236,
                      "login": "yob"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "143 public repos, account ~18 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 143
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 18
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 91,
            "inputs": {
              "packages": [
                "pdf-reader"
              ],
              "ecosystems": "rubygems",
              "any_deprecated": false,
              "min_days_since_publish": 205
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on rubygems",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "rubygems"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 205 days ago",
                "points": 26,
                "status": "partial",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 205
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "64 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 64
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "at_risk",
        "name": "Engineering Quality",
        "value": 40,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "at_risk",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_ci": false,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "8 out of 9 merged PRs checked by a CI test -- score normalized to 8",
                "points": 16,
                "status": "partial",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "at_risk",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 51,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 39,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 14,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 4,
              "scorecard_aggregate": 3.9
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "8 out of 9 merged PRs checked by a CI test -- score normalized to 8",
                "points": 2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 1/11 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 26 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 2 resolved dependencies against OSV; 13 could not be assessed (no resolved version, an unsupported ecosystem, or beyond the reported package list). This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories",
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 2
                }
              },
              {
                "code": "advisories_unassessed",
                "params": {
                  "count": 13
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 0,
              "affected_packages": 0,
              "assessed_packages": 2,
              "unassessed_packages": 13,
              "affected_by_severity": "none",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "transitive set not separable from development and test dependencies in this scope",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_scope_not_separable",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 2,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 15
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "at_risk",
        "name": "AI Readiness",
        "value": 40,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.75,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "75 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 75,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 34,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": true,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.01,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "1 of the last 100 commits agent-authored or agent-credited",
                "points": 2,
                "status": "partial",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 1,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "moderate",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "primary_language": "Ruby",
              "largest_source_bytes": 63485,
              "source_files_sampled": 133,
              "oversized_source_files": 1
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Ruby without a type-check config",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_typecheck_config_language",
                    "params": {
                      "language": "Ruby"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "1/133 source files over 60KB",
                "points": 54.6,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 133,
                      "oversized": 1
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [],
  "report_type": "repository",
  "generated_at": "2026-07-21T23:33:54.042750Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/y/yob/pdf-reader.svg",
  "full_name": "yob/pdf-reader",
  "license_state": "standard",
  "license_spdx": "MIT"
}

Оцінки — це сигнали, а не гарантії. Вони відображають публічно видимі практики на GitHub — це не аудит коду й не гарантія безпеки.

Відсутні дані виключаються, а ваги перенормовуються — нуль за відсутність ніколи не ставиться. Методологія версіонована й відкрита: метрики v1.13.0, схема v0.26.0 — повна методологія · вікі метрик.

Як окремий результат виглядає на тлі всього реєстру: сукупна статистикаRubyGems.