公开记录
软件健康报告模式 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年6月在 GitHub 上查看 ↗

yob/pdf-reader 的健康指数为 100 分中的 59 分,处于「中等」区间。 其得分最高的类别是Community & Adoption(76/100),最低的是AI Readiness(40/100)。 最近一次更新在 6 天前。 近期的大部分工作由 1 位贡献者完成。

59
总分 / 100
中等

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。

59
优秀85-100堪称典范;基本满足所有检验标准
良好70-84健康;仅有轻微不足
中等50-69可接受,但存在明显不足;建议进行审查
存在风险30-49存在重大薄弱环节;采用时应保持审慎
危急1-29问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。

所有权

James Healy个人账户
236 关注者143 个公开仓库始于 2008年4月

该仓库由个人账户拥有。相较于组织支持的项目,单一所有者项目的延续性风险更高。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
RubyGemspdf-reader2.15.1-64205 天前

按类别列示的指标

活力

项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?

64中等 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 6 天前
10.4/36提交节奏 — 52 周中有 15 周有提交
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

发布纪律

50中等
评分方式
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

社区健康

50中等
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(MIT)
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template
评分方式
80/80累计下载量 — rubygems 合计历史 109,562,630 次下载
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议题解决 — 77% 的议题已关闭
31.8/38.3PR 接受 — 已裁定的 PR 中 282/339 已合并
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所有者影响力 — yob 有 236 位关注者
25/25既往记录 — 143 个公开仓库,账户约 18 年
所用输入
followers236
owner_typeUser
is_verified
owner_loginyob
public_repos143
account_age_days6,664
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — rubygems 上有 1 个软件包
26/35发布时效 — 最近一次发布于 205 天前
20/20版本历史 — 64 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagespdf-reader
ecosystemsrubygems
any_deprecated
min_days_since_publish205

工程质量

基础的工程与文档实践是否到位?

40存在风险 · 占总体的 20%

工程实践

40存在风险
评分方式
0/24CI 工作流
24/24存在测试
0/16Linter 配置
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 项无法评估——没有已解析的版本、生态系统不受支持,或超出所报告的软件包清单。 该仓库未发布任何索引可解析的软件包,因此改为评估仓库依赖图。该图将开发与测试版本固定同交付的依赖混在一起,因此仅对声明的运行时依赖计分;传递性发现仅作为背景信息列出,不计入评分。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。

40存在风险 · 占总体的 0%
评分方式
0/45代理指令 — 没有 CLAUDE.md / AGENTS.md / 编辑器规则
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 75 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.75
agent_instruction_files
agent_instruction_max_bytes
评分方式
0/18一条命令的引导启动
22/22自动化测试
0/11Lint / 格式化配置
0/11静态类型检查
10/10可复现环境 — Dockerfile
2/10已体现的代理实践 — 最近 100 次提交中有 1 次由代理编写或署名代理
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可控的文件大小 — 采样的 133 个源文件中有 1 个超过 60KB
所用输入
primary_languageRuby
largest_source_bytes63,485
source_files_sampled133
oversized_source_files1

机器可读接口

40存在风险
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
0/20MCP 服务器
40/40可运行示例 — examples
所用输入
example_dirsexamples
has_mcp_signal
api_schema_files

关键数据

1,925GitHub 星标
61贡献者
121最近 12 个月提交数
6距最近推送天数
64发布版本数
1巴士系数(bus factor)
61开放议题
RubyGems软件包生态系统数

更多细节

Star 与 Fork 历史 1,925 ★ / 284 ⇿
1,925Star
284Fork
55发布

每颗 star 和每个 fork 的添加时间,来自 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 个间接(传递)软件包。仓库提交锁文件时,传递闭包才是完整的。

注册表软件包版本关系
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.