公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-25 17:21 UTC

openrewrite / rewrite-static-analysis

OpenRewrite recipes for identifying and fixing static analysis issues.

Java自定义许可证★ 58 星标⑂ 102 复刻始于 2023年4月在 GitHub 上查看 ↗

openrewrite/rewrite-static-analysis 的健康指数为 100 分中的 72 分,处于「良好」区间。 其得分最高的类别是Vitality(98/100),最低的是Security(52/100)。 最近一次更新在 1 天前。 近期的大部分工作由 4 位贡献者完成。

72
总分 / 100
良好

软件健康指数

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

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

评分画像

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

所有权

984 关注者75 个公开仓库始于 2020年2月

该仓库由组织支持——共同承担、可问责的托管责任,可延续于任何单一维护者之后。

按类别列示的指标

活力

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

98优秀 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 1 天前
32.5/36提交节奏 — 52 周中有 47 周有提交
18/18提交量 — 最近一年 253 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 11 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year253
human_commit_share1
days_since_last_push1
active_weeks_last_year47

发布纪律

100优秀
评分方式
27/27有发布版本 — 已发布 91 个发布版本
36/36发布时效 — 最近一次发布版本于 11 天前
27/27发布节奏 — 约每 10.7 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count91
latest_release_tagv2.39.0
releases_from_tags
days_since_latest_release11
mean_days_between_releases10.7
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?

60中等 · 占总体的 18%
评分方式
28.5/60星标 — 58 个星标
16.7/25复刻 — 102 个复刻
4.3/15关注者 — 7 位关注者
所用输入
forks102
stars58
watchers7
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

71良好
评分方式
22.5/22.5README
16.9/22.5许可证 — 存在许可证文件,但不是可识别的许可证
18/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
6.3/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template

可持续性与治理

项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?

77良好 · 占总体的 24%
评分方式
43.2/54巴士系数 — 4 位贡献者贡献了半数提交
17.6/22.5提交分布 — 头号贡献者编写了 22% 的提交
13.5/13.5贡献者广度 — 98 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 22 contributing companies or organizations
所用输入
bus_factor4
contributors_sampled98
top_contributor_share0.217
评分方式
33.7/46.8议题解决 — 72% 的议题已关闭
32.2/38.3PR 接受 — 已裁定的 PR 中 427/508 已合并
3/15OpenSSF Scorecard:Code-Review — Found 8/30 approved changesets -- score normalized to 2
所用输入
merged_prs427
open_issues116
closed_issues298
issue_closed_ratio0.72
closed_unmerged_prs81
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
21.5/25所有者影响力 — openrewrite 有 984 位关注者
25/25既往记录 — 75 个公开仓库,账户约 6 年
所用输入
followers984
owner_typeOrganization
is_verified
owner_loginopenrewrite
public_repos75
account_age_days2,341

工程质量

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

63中等 · 占总体的 20%

工程实践

72良好
评分方式
24/24CI 工作流 — 4 个工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
6.4/6.4.editorconfig
18/20OpenSSF Scorecard:CI-Tests — 21 out of 23 merged PRs checked by a CI test -- score normalized to 9
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config

文档

50中等
评分方式
30/30README
0/25文档目录
0/15文档 / 主页站点
10/10仓库描述
10/10主题标签 — 6 个主题标签
0/10Wiki
所用输入
topicsgood-first-issue, java, static-analysis, static-code-analysis, openrewrite, openrewrite-recipes
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?

52中等 · 占总体的 16%

安全态势

52中等
评分方式
6.8/7.5Binary-Artifacts — binaries present in source code
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.2/2.5CI-Tests — 21 out of 23 merged PRs checked by a CI test -- score normalized to 9
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
1.5/7.5Code-Review — Found 8/30 approved changesets -- score normalized to 2
2.5/2.5Contributors — project has 22 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.2/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 11 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 — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate5.2
已排除计分(无数据或不适用):packaging, signed_releases。 其余权重已重新归一化。

AI 就绪度

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

73良好 · 占总体的 0%
评分方式
45/45代理指令 — CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 91 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.91
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes8,599
评分方式
12.6/18一条命令的引导启动 — build.gradle.kts(工具链约定,无任务运行器)
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — Java(静态类型)
0/10可复现环境
2/10已体现的代理实践 — 最近 100 次提交中有 1 次由代理编写或署名代理
5/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_manifestsbuild.gradle.kts
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — Java(静态类型)
54.7/55可控的文件大小 — 采样的 403 个源文件中有 2 个超过 60KB
所用输入
primary_languageJava
largest_source_bytes88,413
source_files_sampled403
oversized_source_files2

关键数据

58GitHub 星标
98贡献者
253最近 12 个月提交数
1距最近推送天数
91发布版本数
4巴士系数(bus factor)
116开放议题
Maven软件包生态系统数

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token

更多细节

Star 与 Fork 历史 0 ★ / 102 ⇿
0Star
102Fork
91发布

每颗 star 和每个 fork 的添加时间,来自 GitHub 并按天汇总。累计增长位于其构成来源——每日新增——的正上方,二者可相互对照:稳定的自然增长与短暂的突增形态截然不同。当这一差别可被衡量时,它会作为增长真实性予以报告。

02040608010012010132023-052024-122026-07
主版本 2次版本 61修订 28

每个点涵盖 3 天。

OpenSSF Scorecard 5.2 / 10
5.2综合

来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。Scorecard v5.5.0 · 2026-07-25 17:21 UTC

9Binary-Artifactsbinaries present in source code
0Branch-Protectionbranch protection not enabled on development/release branches
9CI-Tests21 out of 23 merged PRs checked by a CI test -- score normalized to 9
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
2Code-ReviewFound 8/30 approved changesets -- score normalized to 2
10Contributorsproject has 22 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
9Licenselicense file detected
10Maintained30 commit(s) and 11 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
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
全部依赖 0

来自 GitHub 依赖图的完整解析依赖集合:0 个直接依赖与 0 个间接(传递)软件包。仓库提交锁文件时,传递闭包才是完整的。

注册表软件包版本关系
依赖安全公告 未评估

本报告未能完成公告比对:No resolved dependencies to assess

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "good-first-issue",
        "java",
        "static-analysis",
        "static-code-analysis",
        "openrewrite",
        "openrewrite-recipes"
      ],
      "is_fork": false,
      "size_kb": 5108,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Java": 3334875
      },
      "pushed_at": "2026-07-23T19:32:48Z",
      "created_at": "2023-04-30T23:54:01Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-23T19:32:53Z",
      "description": "OpenRewrite recipes for identifying and fixing static analysis issues.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": "NOASSERTION",
      "primary_language": "Java",
      "significant_languages": [
        "Java"
      ]
    },
    "owner": {
      "blog": "https://docs.openrewrite.org",
      "name": "OpenRewrite",
      "type": "Organization",
      "login": "openrewrite",
      "company": null,
      "location": "San Francisco, CA",
      "followers": 984,
      "avatar_url": "https://avatars.githubusercontent.com/u/61478321?v=4",
      "created_at": "2020-02-25T21:27:36Z",
      "is_verified": null,
      "public_repos": 75,
      "account_age_days": 2341
    },
    "license": {
      "state": "custom",
      "spdx_id": null,
      "raw_spdx": "NOASSERTION",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.39.0",
          "kind": "minor",
          "published_at": "2026-07-14T05:34:02Z"
        },
        {
          "tag": "v2.38.0",
          "kind": "minor",
          "published_at": "2026-07-01T06:00:05Z"
        },
        {
          "tag": "v2.37.0",
          "kind": "minor",
          "published_at": "2026-06-17T09:01:31Z"
        },
        {
          "tag": "v2.36.0",
          "kind": "minor",
          "published_at": "2026-06-03T13:47:42Z"
        },
        {
          "tag": "v2.35.0",
          "kind": "minor",
          "published_at": "2026-05-21T10:35:26Z"
        },
        {
          "tag": "v2.34.1",
          "kind": "patch",
          "published_at": "2026-05-07T01:21:31Z"
        },
        {
          "tag": "v2.34.0",
          "kind": "minor",
          "published_at": "2026-04-27T09:38:22Z"
        },
        {
          "tag": "v2.33.1",
          "kind": "patch",
          "published_at": "2026-04-23T10:05:24Z"
        },
        {
          "tag": "v2.33.0",
          "kind": "minor",
          "published_at": "2026-04-21T07:52:41Z"
        },
        {
          "tag": "v2.32.0",
          "kind": "minor",
          "published_at": "2026-04-08T12:57:29Z"
        },
        {
          "tag": "v2.31.0",
          "kind": "minor",
          "published_at": "2026-03-25T09:46:47Z"
        },
        {
          "tag": "v2.30.1",
          "kind": "patch",
          "published_at": "2026-03-19T15:55:58Z"
        },
        {
          "tag": "v2.30.0",
          "kind": "minor",
          "published_at": "2026-03-12T14:29:03Z"
        },
        {
          "tag": "v2.29.0",
          "kind": "minor",
          "published_at": "2026-03-04T17:03:53Z"
        },
        {
          "tag": "v2.28.0",
          "kind": "minor",
          "published_at": "2026-02-25T12:46:09Z"
        },
        {
          "tag": "v2.27.0",
          "kind": "minor",
          "published_at": "2026-02-11T09:05:07Z"
        },
        {
          "tag": "v2.26.0",
          "kind": "minor",
          "published_at": "2026-01-20T19:25:15Z"
        },
        {
          "tag": "v2.25.0",
          "kind": "minor",
          "published_at": "2026-01-07T16:01:56Z"
        },
        {
          "tag": "v2.24.0",
          "kind": "minor",
          "published_at": "2025-12-16T16:40:14Z"
        },
        {
          "tag": "v2.23.0",
          "kind": "minor",
          "published_at": "2025-12-05T11:02:22Z"
        },
        {
          "tag": "v2.22.0",
          "kind": "minor",
          "published_at": "2025-11-20T11:46:55Z"
        },
        {
          "tag": "v2.21.0",
          "kind": "minor",
          "published_at": "2025-11-04T15:00:03Z"
        },
        {
          "tag": "v2.20.0",
          "kind": "minor",
          "published_at": "2025-10-22T12:03:34Z"
        },
        {
          "tag": "v2.19.0",
          "kind": "minor",
          "published_at": "2025-10-10T17:18:06Z"
        },
        {
          "tag": "v2.18.0",
          "kind": "minor",
          "published_at": "2025-09-24T12:37:03Z"
        },
        {
          "tag": "v2.17.0",
          "kind": "minor",
          "published_at": "2025-09-10T10:50:57Z"
        },
        {
          "tag": "v2.16.0",
          "kind": "minor",
          "published_at": "2025-08-27T16:18:09Z"
        },
        {
          "tag": "v2.15.0",
          "kind": "minor",
          "published_at": "2025-08-12T21:08:15Z"
        },
        {
          "tag": "v2.14.0",
          "kind": "minor",
          "published_at": "2025-07-23T21:44:08Z"
        },
        {
          "tag": "v2.13.0",
          "kind": "minor",
          "published_at": "2025-07-23T10:47:33Z"
        },
        {
          "tag": "v2.12.0",
          "kind": "minor",
          "published_at": "2025-07-09T15:16:16Z"
        },
        {
          "tag": "v2.11.0",
          "kind": "minor",
          "published_at": "2025-06-25T11:26:25Z"
        },
        {
          "tag": "v2.10.0",
          "kind": "minor",
          "published_at": "2025-05-28T15:32:59Z"
        },
        {
          "tag": "v2.9.0",
          "kind": "minor",
          "published_at": "2025-05-07T17:18:47Z"
        },
        {
          "tag": "v2.8.0",
          "kind": "minor",
          "published_at": "2025-04-24T17:43:56Z"
        },
        {
          "tag": "v2.7.1",
          "kind": "patch",
          "published_at": "2025-04-10T15:15:15Z"
        },
        {
          "tag": "v2.7.0",
          "kind": "minor",
          "published_at": "2025-04-09T18:53:52Z"
        },
        {
          "tag": "v2.6.0",
          "kind": "minor",
          "published_at": "2025-04-07T10:20:32Z"
        },
        {
          "tag": "v2.5.1",
          "kind": "patch",
          "published_at": "2025-03-27T19:12:36Z"
        },
        {
          "tag": "v2.5.0",
          "kind": "minor",
          "published_at": "2025-03-26T10:51:19Z"
        },
        {
          "tag": "v2.4.0",
          "kind": "minor",
          "published_at": "2025-03-11T19:42:05Z"
        },
        {
          "tag": "v2.3.0",
          "kind": "minor",
          "published_at": "2025-02-20T21:13:03Z"
        },
        {
          "tag": "v2.2.0",
          "kind": "minor",
          "published_at": "2025-02-07T16:57:10Z"
        },
        {
          "tag": "v2.1.0",
          "kind": "minor",
          "published_at": "2025-01-24T17:30:23Z"
        },
        {
          "tag": "v2.0.2",
          "kind": "patch",
          "published_at": "2025-01-17T17:24:18Z"
        },
        {
          "tag": "v2.0.1",
          "kind": "patch",
          "published_at": "2025-01-11T15:09:11Z"
        },
        {
          "tag": "v2.0.0",
          "kind": "major",
          "published_at": "2025-01-10T17:09:56Z"
        },
        {
          "tag": "v1.22.0",
          "kind": "minor",
          "published_at": "2024-12-18T15:14:20Z"
        },
        {
          "tag": "v1.21.1",
          "kind": "patch",
          "published_at": "2024-11-28T18:55:34Z"
        },
        {
          "tag": "v1.21.0",
          "kind": "minor",
          "published_at": "2024-11-27T16:16:52Z"
        },
        {
          "tag": "v1.20.0",
          "kind": "minor",
          "published_at": "2024-11-13T16:12:32Z"
        },
        {
          "tag": "v1.19.0",
          "kind": "minor",
          "published_at": "2024-10-23T15:04:27Z"
        },
        {
          "tag": "v1.18.0",
          "kind": "minor",
          "published_at": "2024-10-09T18:16:41Z"
        },
        {
          "tag": "v1.17.0",
          "kind": "minor",
          "published_at": "2024-09-24T19:06:45Z"
        },
        {
          "tag": "v1.16.0",
          "kind": "minor",
          "published_at": "2024-09-11T17:22:09Z"
        },
        {
          "tag": "v1.15.0",
          "kind": "minor",
          "published_at": "2024-08-28T14:16:51Z"
        },
        {
          "tag": "v1.14.0",
          "kind": "minor",
          "published_at": "2024-08-12T19:47:32Z"
        },
        {
          "tag": "v1.13.0",
          "kind": "minor",
          "published_at": "2024-07-31T11:54:56Z"
        },
        {
          "tag": "v1.12.0",
          "kind": "minor",
          "published_at": "2024-07-15T09:14:18Z"
        },
        {
          "tag": "v1.11.0",
          "kind": "minor",
          "published_at": "2024-07-03T16:51:43Z"
        },
        {
          "tag": "v1.10.1",
          "kind": "patch",
          "published_at": "2024-06-19T18:05:17Z"
        },
        {
          "tag": "v1.10.0",
          "kind": "minor",
          "published_at": "2024-06-19T09:04:23Z"
        },
        {
          "tag": "v1.9.0",
          "kind": "minor",
          "published_at": "2024-06-07T22:36:01Z"
        },
        {
          "tag": "v1.8.1",
          "kind": "patch",
          "published_at": "2024-05-22T21:47:41Z"
        },
        {
          "tag": "v1.8.0",
          "kind": "minor",
          "published_at": "2024-05-22T16:03:40Z"
        },
        {
          "tag": "v1.7.0",
          "kind": "minor",
          "published_at": "2024-05-18T05:20:04Z"
        },
        {
          "tag": "v1.6.0",
          "kind": "minor",
          "published_at": "2024-05-08T13:50:25Z"
        },
        {
          "tag": "v1.5.0",
          "kind": "minor",
          "published_at": "2024-04-24T15:23:21Z"
        },
        {
          "tag": "v1.4.2",
          "kind": "patch",
          "published_at": "2024-03-19T18:48:18Z"
        },
        {
          "tag": "v1.4.1",
          "kind": "patch",
          "published_at": "2024-03-19T13:12:21Z"
        },
        {
          "tag": "v1.4.0",
          "kind": "minor",
          "published_at": "2024-03-12T22:04:15Z"
        },
        {
          "tag": "v1.3.1",
          "kind": "patch",
          "published_at": "2024-02-20T20:19:26Z"
        },
        {
          "tag": "v1.3.0",
          "kind": "minor",
          "published_at": "2024-02-06T18:34:52Z"
        },
        {
          "tag": "v1.2.2",
          "kind": "patch",
          "published_at": "2024-01-23T17:11:31Z"
        },
        {
          "tag": "v1.2.1",
          "kind": "patch",
          "published_at": "2024-01-16T16:01:31Z"
        },
        {
          "tag": "v1.2.0",
          "kind": "minor",
          "published_at": "2024-01-09T14:37:38Z"
        },
        {
          "tag": "v1.1.4",
          "kind": "patch",
          "published_at": "2023-12-21T13:53:07Z"
        },
        {
          "tag": "v1.1.3",
          "kind": "patch",
          "published_at": "2023-12-08T10:26:38Z"
        },
        {
          "tag": "v1.1.2",
          "kind": "patch",
          "published_at": "2023-12-04T20:05:02Z"
        },
        {
          "tag": "v1.1.1",
          "kind": "patch",
          "published_at": "2023-11-25T10:26:12Z"
        },
        {
          "tag": "v1.1.0",
          "kind": "minor",
          "published_at": "2023-11-11T01:37:59Z"
        },
        {
          "tag": "v1.0.9",
          "kind": "patch",
          "published_at": "2023-10-27T23:56:19Z"
        },
        {
          "tag": "v1.0.8",
          "kind": "patch",
          "published_at": "2023-10-03T03:02:46Z"
        },
        {
          "tag": "v1.0.7",
          "kind": "patch",
          "published_at": "2023-09-12T15:50:05Z"
        },
        {
          "tag": "v1.0.6",
          "kind": "patch",
          "published_at": "2023-08-24T21:22:35Z"
        },
        {
          "tag": "v1.0.5",
          "kind": "patch",
          "published_at": "2023-08-09T16:59:21Z"
        },
        {
          "tag": "v1.0.4",
          "kind": "patch",
          "published_at": "2023-07-26T20:45:34Z"
        },
        {
          "tag": "v1.0.3",
          "kind": "patch",
          "published_at": "2023-07-04T09:11:06Z"
        },
        {
          "tag": "v1.0.2",
          "kind": "patch",
          "published_at": "2023-06-28T12:49:47Z"
        },
        {
          "tag": "v1.0.1",
          "kind": "patch",
          "published_at": "2023-06-14T03:15:35Z"
        },
        {
          "tag": "v1.0.0",
          "kind": "major",
          "published_at": "2023-06-02T02:39:33Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "5545efa3f71cabfb1feeacb55c26ae55538488f5",
          "body": "In Kotlin a newline terminates an expression, so a leading binary operator is\nparsed as a unary operator on a new statement. With the default `WrapOption.NL`\nstyle, `OperatorWrap` moved a binary operator to the start of the next line,\nturning\n\n    val s = \"aaa\" + \"b\" +\n        \"c\"\n\ninto the uncompil\n[…]\nces.\n\nRestrict the visitor to `J.CompilationUnit` so it only reformats Java and leaves\nKotlin (and other non-Java `JavaSourceFile`s) untouched.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Do not wrap operators onto a new line in Kotlin sources (#936)",
          "author_name": "Vladimir Sitnikov",
          "author_login": "vlsi",
          "committed_at": "2026-07-23T19:32:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8a88b480f019d45a9e39f873d51da343e6e9ccbf",
          "body": "* Add recipe for finding exceptions which are thrown from catch blocks that do not reference the caught exception\n\n* Add recipe for finding exceptions which are thrown from catch blocks that do not reference the caught exception\n\n* Update recipes.csv",
          "is_bot": false,
          "headline": "exception-without-cause (#950)",
          "author_name": "Sam Snyder",
          "author_login": "sambsnyd",
          "committed_at": "2026-07-23T10:15:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9188c1359bfc56a87ba0679193b190b286c87225",
          "body": "…949)",
          "is_bot": false,
          "headline": "Add recipes for migrating off a variety of legacy collection types (#…",
          "author_name": "Sam Snyder",
          "author_login": "sambsnyd",
          "committed_at": "2026-07-23T08:11:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bcf245c14aaadff8b55811600364f452cf5db3cd",
          "body": null,
          "is_bot": false,
          "headline": "Add recipe for finding public methods missing javadoc (#948)",
          "author_name": "Sam Snyder",
          "author_login": "sambsnyd",
          "committed_at": "2026-07-23T03:22:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8e4b8c838d327c007050695c55f51470f18adfce",
          "body": null,
          "is_bot": false,
          "headline": "Set Develocity `projectId` to \"openrewrite\" (#947)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-07-22T15:12:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "13da5141b7690ce04b8f5a0767641f23cb2b67e0",
          "body": "Co-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "Move Develocity to community.develocity.cloud",
          "author_name": "tim@moderne.io",
          "author_login": "timtebeek",
          "committed_at": "2026-07-22T12:14:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2095f87cfb10bee9076fb42946dc5ff5d2826236",
          "body": null,
          "is_bot": false,
          "headline": "Consistently order test annotations",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-07-22T09:43:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1b1514253c3991792548fde5f69354d78a2df1a9",
          "body": "…ment position on instance methods too (#946)\n\nThe argument-position branch only guarded static methods (via\nshouldRetainOnStaticMethod) against removing a witness whose type\nvariables aren't inferable from the call's own arguments. Instance\nmethods used as arguments skipped that guard entirely, so \n[…]\nesolved.\n\nGeneralize the check to apply regardless of static/instance, matching\nthe reasoning already used for the sibling select-position case.\n\nCo-authored-by: Neil Mushell <neil.mushell@airbnb.com>",
          "is_bot": false,
          "headline": "UnnecessaryExplicitTypeArguments: retain load-bearing witness in argu…",
          "author_name": "neil-mushell",
          "author_login": "neil-mushell",
          "committed_at": "2026-07-21T15:01:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bc8d038cfd4d533758674d57876ce7a1561baf18",
          "body": "…rs (#943)\n\n* FixStringFormatExpressions: do not strip args for unresolved placeholders\n\nWhen a String#format/formatted call's format string has zero real `%`\nconversion specifiers, the recipe treated every trailing argument as\ndead code and deleted it. That's wrong when the string contains `{}`\ntok\n[…]\n\n* Retry CI (flaky TypeScript RPC failure unrelated to this change)\n\n* Minimize comments\n\n---------\n\nCo-authored-by: Neil Mushell <neil.mushell@airbnb.com>\nCo-authored-by: Tim te Beek <tim@moderne.io>",
          "is_bot": false,
          "headline": "FixStringFormatExpressions: don't strip args with no matched specifie…",
          "author_name": "neil-mushell",
          "author_login": "neil-mushell",
          "committed_at": "2026-07-17T12:43:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9a1dd5ed8de653f919cc6aca343c47f1d6fbc00d",
          "body": "…rence (#942)\n\nWhen a lambda calls an unqualified method belonging to an enclosing\n(outer) class from within an inner class, the recipe emitted `this::m`,\nwhich does not compile since `this` refers to the inner instance. Emit\n`Outer.this::m` in that case.\n\nFixes #941",
          "is_bot": false,
          "headline": "Qualify `this` for outer-class methods in ReplaceLambdaWithMethodRefe…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-07-15T09:06:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f3e03f6d367da5305f4f30ea10d8368c0ebaf52c",
          "body": "`UnnecessaryThrows` stripped `throws` from a package-private method whose\nown body never throws, breaking a subclass override (in another file) that\ndoes throw the exception, since the LST has no downward override links to\ndetect it.\n\nExtend the \"may be overridden\" guard from `protected` to also cov\n[…]\nge-private methods, and add same-compilation-unit override detection\nso exceptions still declared by a same-file override are retained. Update\nthe recipe description to note the cross-file limitation.",
          "is_bot": false,
          "headline": "Retain UnnecessaryThrows on overridable methods (#939) (#940)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-07-14T13:11:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e51c700117e6d1bbb4c8a6e32d5f590e457b8e12",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.java.recipes.ExamplesExtractor?organizationId=QUxML01vZGVybmUgKyBPcGVuUmV3cml0ZQ%3D%3D\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "Extract documentation examples from tests",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-07-14T05:04:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7cb9e591c9810dc99625105bd1bf543f9487cda3",
          "body": "…late (#937)",
          "is_bot": false,
          "headline": "Consolidate UseStringCaseInsensitiveOrder into a single Refaster temp…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-07-13T08:12:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6108d5fd97f08b527f646f7b19a2ace4c6f445b8",
          "body": "Co-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "OpenRewrite recipe best practices",
          "author_name": "timtebeek@gmail.com",
          "author_login": "timtebeek",
          "committed_at": "2026-07-13T07:43:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a303997a0a3b097f2898a588521564e785047df3",
          "body": "* Python: add Python tests for selected 7 recipes\n\n* Install the Python engine into a local dir for tests\n\nRegister a LauncherSessionListener that configures the shared rewrite-python\nRPC engine with pipPackagesPath=.rewrite-python (gitignored), so CI installs\nthe exact jar-matching openrewrite package from PyPI instead of requiring it\npreinstalled on the interpreter. REWRITE_PYTHON_PATH overrides the interpreter\nfor testing against locally-built (.dev0) rewrite-python.",
          "is_bot": false,
          "headline": "Python: add Python tests for selected 7 recipes (#929)",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-07-08T13:42:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4aff89879c7e91288110e195a91c3ceb50ae65f1",
          "body": "* Keep (Object) cast on array argument at varargs position\n\nAn (Object) cast on an array-typed argument at the varargs position is\nnot redundant: it marks the array as a single varargs element rather\nthan being spread, and silences Error Prone's\nPrimitiveArrayPassedToVarargsMethod. Removing it changes call semantics.\n\nFixes #934\n\n* Merge varargs cast guards into a single check\n\n* Minimize comment",
          "is_bot": false,
          "headline": "Keep (Object) cast on array argument at varargs position (#935)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-07-06T13:17:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "35794f97b00fc56472ae6c4bef49e4c34420bb0a",
          "body": null,
          "is_bot": false,
          "headline": "Another UseDiamondOperator varargs fix",
          "author_name": "Sam Snyder",
          "author_login": "sambsnyd",
          "committed_at": "2026-07-03T20:57:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03e2bccadff0ebb66b46495407c3d31e1067ec13",
          "body": "…s (#933)\n\nThe 'best practices' commit changed FromLambda.before() to a method\nreference, making it a duplicate of FromMethodReference and breaking\nmatching of the actual lambda form (a, b) -> a.compareToIgnoreCase(b).",
          "is_bot": false,
          "headline": "Fix UseStringCaseInsensitiveOrder FromLambda template to match lambda…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-07-03T09:09:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1b83d00ac60e689f29cc4dacad43c166ee41046e",
          "body": "Co-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "OpenRewrite recipe best practices",
          "author_name": "tim@moderne.io",
          "author_login": "timtebeek",
          "committed_at": "2026-07-03T08:56:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6ed9dfda99335f2763d947d9081bdd1bb70b53d0",
          "body": "…1+ (#930)\n\nUseTryWithResources always emitted a named resource variable, even when\nthe resource is never referenced in the try body. Under -Xlint:all -Werror\nthat unused variable fails the build.\n\nWhen the resource is unused in the try body and the target Java version is\n>= 21, emit the unnamed variable _ (JEP 443/456) instead.\n\nFixes #927",
          "is_bot": false,
          "headline": "Use unnamed variable for unused try-with-resources resource on Java 2…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-06-30T16:56:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "be7f5943e9a48262a09a5f23e3a69de7a760b005",
          "body": "* Add RemoveUnreachableMultiCatchAlternative\n\nRemoves `catch` alternatives that are already covered by an earlier\n`catch` clause in the same `try`. When a multi-catch reduces to a\nsingle alternative it collapses to a regular `catch`; when all\nalternatives are shadowed the entire `catch` clause is dr\n[…]\nemoveImport for shadowed types that are removed, and add a\ntest covering specific catches retained before a trailing catch-all\nException block.\n\n---------\n\nCo-authored-by: Tim te Beek <tim@moderne.io>",
          "is_bot": false,
          "headline": "Add RemoveUnreachableMultiCatchAlternative (#926)",
          "author_name": "Steve Elliott",
          "author_login": "steve-aom-elliott",
          "committed_at": "2026-06-30T12:07:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4adaeaccd0b50777e8d77c41f8e9ce550b3fdc59",
          "body": "…(#928)\n\n* Test case for Groovy and Kotlin\n\n* Test cases for JS\n\n* typescript() in JS tests\n\n* RemoveUnneededBlock to keep padding if possible\n\n* RemoveUnconditionalValueOverwrite to support JS maps\n\n* Fix RemoveDuplicateConditions test case for JS",
          "is_bot": false,
          "headline": "Tests for Kotlin, Groovy, TS for cross-language code quality recipes …",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-06-30T10:59:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0fb105c4ba732e691d0a45ac082f3d1fe6eccd8d",
          "body": "… target type (#925)\n\nThe lambda/member-reference guard only matched when the cast operand was\nthe direct expression. When the operand is wrapped in parentheses (e.g.\n`(Function<Integer, String>) (i -> ...)`), the operand is a\nJ.ControlParentheses/J.Parentheses, so the guard missed it and the cast\nwas removed. For a `var` local the cast is the sole source of the target\ntype, so removal breaks compilation.\n\nUnwrap parentheses before checking for a lambda or method reference.\n\nFixes #924",
          "is_bot": false,
          "headline": "Fix RemoveRedundantTypeCast removing cast that gives a var lambda its…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-06-29T11:56:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8674121d72babaa6330c55b41e957b28925eeabb",
          "body": "* Add 7 new cross-language code quality recipes\n\nNew recipes implementing SonarQube RSPEC rules with auto-remediation:\n- S1066 CollapsibleIfStatements: merge nested ifs with &&\n- S1656 RemoveSelfAssignment: remove x = x dead assignments\n- S3923 AllBranchesIdentical: collapse if/else where all branch\n[…]\ninitiative covering Java, Go, C#,\nJavaScript, and Python with the same rules in each language.\n\n---------\n\nCo-authored-by: Tim te Beek <tim@moderne.io>\nCo-authored-by: Steve Elliott <steve@moderne.io>",
          "is_bot": false,
          "headline": "Add 7 cross-language code quality recipes (#853)",
          "author_name": "Jonathan Schnéider",
          "author_login": "jkschneider",
          "committed_at": "2026-06-26T13:52:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "51c0f0ef9f61a756332ac726bbacbd637d5cfc7a",
          "body": "Replaces case-insensitive string comparator lambdas and method\nreferences with the JDK constant String.CASE_INSENSITIVE_ORDER:\n\n- (a, b) -> a.compareToIgnoreCase(b)  -> String.CASE_INSENSITIVE_ORDER\n- String::compareToIgnoreCase         -> String.CASE_INSENSITIVE_ORDER\n\nBoth transformations are scop\n[…]\n().compareTo(...)) are\ndeliberately not matched, as the rewrite would change semantics.\n\nAlso regenerates recipes.csv (the existing file was already out of\nsync with recipeCsvGenerate output on main).",
          "is_bot": false,
          "headline": "Add UseStringCaseInsensitiveOrder (#923)",
          "author_name": "Steve Elliott",
          "author_login": "steve-aom-elliott",
          "committed_at": "2026-06-25T11:00:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "66ff7d7411c57644aff020ff7c8fcb4c73d6969b",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/builder/yESIGzVB0?organizationId=QUxML01vZGVybmUgKyBPcGVuUmV3cml0ZQ%3D%3D\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "Recipe best practices",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-06-23T07:37:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ed491a508ab3707ff216bb33d5c409c3d2e40407",
          "body": "…ction arguments (#898)\n\n* Fix RemoveUnusedPrivateMethods removing methods called with raw collections\n\nFix RemoveUnusedPrivateMethods removing methods called with raw collections\n  Match used methods with relaxed parameter types so raw call sites\n  (e.g. Map.keySet()/values()) are not treated as un\n[…]\neUtils.isOfTypeIgnoringGenerics added in openrewrite/rewrite#8035.\n\n---------\n\nCo-authored-by: Muhammad Habiibullah <muhammad.habiibullah@dansmultipro.com>\nCo-authored-by: Tim te Beek <tim@moderne.io>",
          "is_bot": false,
          "headline": "Fix RemoveUnusedPrivateMethods deleting methods called with raw colle…",
          "author_name": "Muhammad Habiibullah",
          "author_login": "habiibullahm",
          "committed_at": "2026-06-18T09:40:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "333720f8c03114efa828e185be7460c29d42a45e",
          "body": "…itch (#922)\n\n`MinimumSwitchCases` threw an `IndexOutOfBoundsException` when visiting a\n`switch` whose `case` arms use Java 21 type-pattern matching (e.g.\n`case Foo.Bar b ->`). Such case labels are not `Expression` instances, so\n`J.Case.getPattern()` calls `get(0)` on an empty list and crashes.\n\nThese switches cannot be converted to `==`/`equals` comparisons anyway, so\n`doRewrite` now bails out when any case label is not a simple expression.\n\nFixes openrewrite/rewrite#8039",
          "is_bot": false,
          "headline": "Fix `MinimumSwitchCases` crash on Java 21 sealed-interface pattern sw…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-06-17T10:43:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83e4fd588b743a7e72d4dbce1927188b0b25718b",
          "body": "…(#921)\n\nThe recipe only checked for close() calls in catch blocks, but any\nreference to the resource from a catch clause becomes out of scope once\nthe declaration moves into the try-with-resources header. A resource's\nscope is the try block only (JLS 14.20.3), so the resulting code failed\nto compile.\n\nCloses #920",
          "is_bot": false,
          "headline": "Fix UseTryWithResources moving resource out of scope for catch block …",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-06-17T10:42:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3d2b173582bfa494a821db59cd4aac932447bb5a",
          "body": "…… (#868)\n\n* Fix false positive in `AnnotateNullableParameters` when parameter dereferenced before null check\n\n* Simplify `NullCheckAndDereferenceVisitor` in `AnnotateNullableParameters`\n\nReplace cursor-message state with plain instance fields keyed by\n`JavaType.Variable` so scope-shadowed identifie\n[…]\nnt lexical dereference tracking and add guard-clause test in AnnotateNullableParameters\n\n---------\n\nCo-authored-by: stefanod <stefano.dallapalma@adyen.com>\nCo-authored-by: Tim te Beek <tim@moderne.io>",
          "is_bot": false,
          "headline": "Fix false positive in `AnnotateNullableParameters` when parameter der…",
          "author_name": "Stefano Dalla Palma",
          "author_login": "stefanodallapalma",
          "committed_at": "2026-06-16T20:28:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6d76624d354fae455f635a9dcdbf728e51f5d1bb",
          "body": "…ing on a varargs method (#919)",
          "is_bot": false,
          "headline": "Fix UseDiamondOperator throwing array index out of bounds when operat…",
          "author_name": "Sam Snyder",
          "author_login": "sambsnyd",
          "committed_at": "2026-06-16T00:38:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dfc6176386b69bed093340028cccbfe49fe998e4",
          "body": "* Explain InstanceOfDoubleUnboxinIssue in InstanceOfPatternMatchTest.java\n\n* InstanceOfPatternMatch: preserve double casting\n\n---------\n\nCo-authored-by: Harald Aamot <harald.aamot@sap.com>",
          "is_bot": false,
          "headline": "`InstanceOfPatternMatch` not to remove double primitive cast (#918)",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-06-15T06:42:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "49d1bdcc342179b7e6420f3582d4e22269fc238e",
          "body": "…yword (#913)\n\nWhen a type cast directly follows a keyword without intervening\nwhitespace (e.g. `throw(Foo)e`), replacing the cast with the new pattern\nvariable identifier fused the tokens into `throwexception`, producing\nuncompilable code. Insert a single space in that case for `throw`,\n`return` and `yield`.\n\nFixes openrewrite/rewrite-apache#135",
          "is_bot": false,
          "headline": "Preserve space when InstanceOfPatternMatch replaces a cast after a ke…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-06-12T11:06:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "23503ce7ff7443c7a41b3c7360b0b5f63ffa6ff0",
          "body": "…dantTypeCast` (#915)\n\nFixes #914",
          "is_bot": false,
          "headline": "Preserve raw supertype cast on parameterized argument in `RemoveRedun…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-06-12T10:08:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "64e3203d705fd02f078318e230fab7447d61e04a",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.AddToGitignore?organizationId=QUxML01vZGVybmUgKyBPcGVuUmV3cml0ZQ%3D%3D#defaults=W3sidmFsdWUiOiIuY29udGV4dC8iLCJuYW1lIjoiZW50cmllcyJ9XQ==\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "git-ignore .context/",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-06-09T11:31:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "01d4a78ff634c52eedd320449b665ebe9dc272af",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.gradle.UpdateGradleWrapper?organizationId=QUxML01vZGVybmUgKyBPcGVuUmV3cml0ZS9PcGVuUmV3cml0ZQ%3D%3D#defaults=W3sidmFsdWUiOiI5LjUuMSIsIm5hbWUiOiJ2ZXJzaW9uIn0seyJ2YWx1ZSI6ImJpbiIsIm5hbWUiOiJkaXN0cmlidXRpb24ifSx7InZhbHVlIjoiYmFmYzE0MWI2MTlhZDYzNTBmZDk3NWZjOTAzMTU2ZGQ1YzE1MTk5OGNjOGIwNThlOGMxMDQ0YWI1ZjdiMDMxZiIsIm5hbWUiOiJkaXN0cmlidXRpb25DaGVja3N1bSJ9XQ==\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "Update Gradle wrapper 9.5.1",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-28T19:53:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "421318a90ebb5bd798ce18154e2d9e3f319222f7",
          "body": "…plicitTypeArguments` (#911)\n\n`UnnecessaryExplicitTypeArguments` removed an explicit type witness from a\ngeneric method invocation even when that invocation was the select (receiver)\nof another method invocation. In that position there is no target type to drive\ninference, so the witness is load-bea\n[…]\ne witness is retained unless the type variables\nare inferable from the call's own arguments; the existing argument-position and\nstatic-method behavior is preserved by reusing the same inference check.",
          "is_bot": false,
          "headline": "Retain load-bearing type witness in select position in `UnnecessaryEx…",
          "author_name": "Knut Wannheden",
          "author_login": "knutwannheden",
          "committed_at": "2026-05-28T18:49:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c4880820742ec1635e75e6d1d4fa3cdc2f67c4ee",
          "body": null,
          "is_bot": false,
          "headline": "Regenerate recipes.csv (#910)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-28T18:36:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "829a5a526a488ab81416d56a8127a703277dbdc0",
          "body": "…mbdaWithMethodReference` (#909)\n\nPreviously the recipe used the method's declaring type to construct\nthe class name, which produced uncompilable references like\n`Base::getValue` (with an inaccessible import) when the declaring\nclass was package-private and the receiver was a public subclass.",
          "is_bot": false,
          "headline": "Use receiver type for unbound instance method reference in `ReplaceLa…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-28T10:28:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ab23a2e5c814612ded17b162d7d14638b6ef3b8",
          "body": "The recipe's `CommentVisitor` is a `JavaIsoVisitor` that crashes in\n`TreeVisitorAdapter` when adapted to Python `Py.CompilationUnit`\nsources. Add a `PythonFileChecker` and use it as a precondition to\nexclude Python files while keeping Java, Kotlin, and Groovy support.",
          "is_bot": false,
          "headline": "Skip Python sources in `CombineSemanticallyEqualCatchBlocks` (#908)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-28T10:24:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e4bcb093e1d3b067816f17208ed0ea839f304ef2",
          "body": "…Cast` (#905)\n\nA raw cast like `(B) b` where `b` is `B<T>` is an intentional unchecked\nconversion; removing it changes overload and type-inference behavior\nwhen the receiver is itself parameterized (e.g. `I<? extends T>`).",
          "is_bot": false,
          "headline": "Preserve raw cast on parameterized expression in `RemoveRedundantType…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-27T08:20:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "62e6a08b356ed8d212c2572bacd17a5f34300de8",
          "body": "…eCast` (#904)\n\nThe overload guard only ran when `castType != expressionType`, so an\n`(Object) value` cast on an `Object` argument fell through and was removed,\nmaking `log(String, Object...)` vs `log(String, Throwable)` calls ambiguous.",
          "is_bot": false,
          "headline": "Preserve cast on argument to overloaded method in `RemoveRedundantTyp…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-26T09:17:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3ef523d451773b1caf7b19b69bc75a6134de3ec0",
          "body": "…(#903)\n\n* Guard `instanceof` to `Class::isInstance` conversion on lambda arity\n\n`ReplaceLambdaWithMethodReference` was converting any single-`instanceof`\nlambda body to `X.class::isInstance` regardless of the lambda's arity or\nwhich identifier was being tested. A `BiPredicate<String, Throwable>` li\n[…]\ny on the resolved `JavaType.Variable`. Switching\nboth to `SemanticallyEqual.areEqual` aligns all three sibling\nbranches on a single, robust check and removes the string match\nfrom the TypeCast branch.",
          "is_bot": false,
          "headline": "Guard `instanceof` to `Class::isInstance` conversion on lambda arity …",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-26T09:13:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "03d153e5ce9be36413ef289b705d716f86431686",
          "body": "…` (#896)\n\n* Replace `var` with interface type in `UseLambdaForFunctionalInterface`\n\nA lambda is a poly expression and needs an explicit target type from\nthe declaration (JLS 14.4.1, 15.27.1), but `var` borrows its type from\nthe right-hand side. Converting `var x = new Foo() {...}` to a lambda\nwhile\n[…]\n that `maybeAddCast` and the\nnew `visitVariableDeclarations` share into a `resolveDiamond` helper, and\ninline the single-use `isVarType` predicate.\n\n* Return directly instead of reassigning the result",
          "is_bot": false,
          "headline": "Replace `var` with interface type in `UseLambdaForFunctionalInterface…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-18T21:10:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8e930b091e48eafefb4e327b9346f96996a9d54d",
          "body": "… (#893)\n\n* Strip diamond operator from cast in `UseLambdaForFunctionalInterface`\n\nThe diamond operator is only valid after `new` (JLS 15.9), not in a cast\nexpression (JLS 15.16). When converting `new Foo<>() {...}` to a lambda\nthat required a cast, the recipe produced invalid `(Foo<>) ...`.\n\n* Rebu\n[…]\nund when\ninferring a diamond's type arguments. Reduce the helper to the only\nreachable path (`FullyQualified`) and add a multi-arg test.\n\n* Drop unused `Space` param and cache `fq.getTypeParameters()`",
          "is_bot": false,
          "headline": "Strip diamond operator from cast in `UseLambdaForFunctionalInterface`…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-18T09:30:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "857aab2b9fe977020797c826f99a7d74b01dbefb",
          "body": "`JavaType.Class#getAnnotations()` returns `List<FullyQualified>`, whose\nelements can be `JavaType.ShallowClass` rather than `JavaType.Annotation`.\nCheck the runtime type before casting to avoid a `ClassCastException`\nwhen the `@Target` meta-annotation is only available as a shallow class.",
          "is_bot": false,
          "headline": "Guard cast to `JavaType.Annotation` in `ReorderAnnotations` (#894)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-18T09:19:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d99ed6f0936dcf8445570ea2e08e8beee87d198a",
          "body": "…#891)\n\n* Preserve cast on generic method invocation in overloaded outer call\n\nWhen a cast wraps a generic method invocation whose declared return is a\ntype variable (e.g. `(Object) cursor.getValue()` where `<T> T getValue()`),\nthe cast pins the inferred return type so an overloaded outer call like\n\n[…]\nbranch\nand the existing Lambda-body branch. Also hoist the cheap\n`hasMethodOverloading` check above the loop so non-overloaded parent\ncalls short-circuit without scanning the declaring type's methods.",
          "is_bot": false,
          "headline": "Preserve cast on generic method invocation in overloaded outer call (…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-16T11:28:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d79cdd4d3fcefd1b18f8f85fa03f5663239f663f",
          "body": "…(#890)\n\n`RemoveRedundantTypeCast` was stripping `(Integer) null` from\n`property.set((Integer) null)` on a `Property<Integer>`, breaking\ncompilation because `Property<T>` declares both `set(T)` and\n`set(Provider<? extends T>)`. The `hasMethodOverloading` guard missed\nthis case: when the receiver is \n[…]\nrized, `getDeclaringType()`\nreturns a `JavaType.Parameterized`, which the `JavaType.Class` filter\ndiscarded. Widen to `JavaType.FullyQualified` so methods on\nparameterized receivers are inspected too.",
          "is_bot": false,
          "headline": "Detect overloads on parameterized receiver in `hasMethodOverloading` …",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-16T11:14:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5e79cd36a83bd77e86579577ea9fa9c15d2a0509",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.recipes.rewrite.OpenRewriteRecipeBestPractices?organizationId=QUxML01vZGVybmUvTW9kZXJuZSArIE9wZW5SZXdyaXRl\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "OpenRewrite recipe best practices",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-16T10:29:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7bea420eb0b7f4c0bc4f0bfe56025e920b5f800b",
          "body": "…ryExplicitTypeArguments` (#889)\n\nWhen a static method declares a type parameter but takes no arguments\n(e.g. `<T> T any()`), the type parameter cannot be inferred from\ncall-site arguments. The existing `shouldRetainOnStaticMethod` guard\nrelied on `JavaType.Method.getDeclaredFormalTypeNames()`, which the\nparser does not always populate, so the guard would incorrectly allow\nremoval and break overload/inference in the enclosing call.",
          "is_bot": false,
          "headline": "Retain explicit type arguments on no-arg static methods in `Unnecessa…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-15T17:09:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "436e8c246033ab48314942869d2f5a26f9895bf0",
          "body": "… (#888)\n\nA cast like `(String) null` passed as the last argument to a varargs\nmethod (e.g. `Method.invoke(Object, Object...)`) is required to\ndisambiguate between passing `null` as the entire array and passing a\nsingle null element. Skip removal when the expression is a `null`\nliteral at the last position whose parameter is an array.",
          "is_bot": false,
          "headline": "Preserve `null` cast at varargs position in `RemoveRedundantTypeCast`…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-15T12:27:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0f017bd5d8bcfbfdb33ec4eaff6091eb99db09de",
          "body": "…to parameterized types (#887)\n\nThe guard against converting `() -> new X()` to `X::new` when `X` has\nmultiple constructors only checked `JavaType.Class`, missing diamond\nexpressions like `new EntityIdForRepositoryVisitor<>()` whose type is\n`JavaType.Parameterized`. The resulting `::new` could become ambiguous\nbetween overloaded `Supplier`/`Function` targets.",
          "is_bot": false,
          "headline": "Extend multi-constructor guard in `ReplaceLambdaWithMethodReference` …",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-15T11:13:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3f61726652d1cc85265508a03c28cdf96bbae160",
          "body": "A class with only private constructors can still be subclassed from within its own body via anonymous classes. Making such a class `final` produces uncompilable code.\n\nFixes #885",
          "is_bot": false,
          "headline": "Skip `FinalClass` when class has anonymous inner subclasses (#886)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-13T16:00:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "932cca99b37a0a32f1fd88878be83afee4e19e34",
          "body": "…orToValueOf` (#883)\n\n`valueOf` may return cached instances, so the rewrite is not behavior-preserving\nfor code that compares boxed values via reference identity, uses\n`System.identityHashCode`, or synchronizes on the boxed value.\n\nRefs #880",
          "is_bot": false,
          "headline": "Document identity-semantics caveat on `PrimitiveWrapperClassConstruct…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-08T09:10:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7ba220a764deb417fef3c1b273665665f145b6f3",
          "body": "…erence (#882)\n\nWhen the first statement is a variable declaration and the following\ncompound assignment's right-hand side references the variable being\ndeclared, folding produced an initializer that read the variable before\nit was assigned, e.g. `int result = state ^ result >>> 1;`.",
          "is_bot": false,
          "headline": "Skip `SimplifyConsecutiveAssignments` when initializer would self-ref…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-06T16:00:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d8acf8bb0ad7bd8521b36ee48096291680791f89",
          "body": "…` crashes (#879)\n\nTwo minimized repros for the `ControlFlowIllegalStateException`s observed in\nflagship runs against `moderneinc/moderne-intellij-plugin` (Kotlin),\n`moderneinc/rewrite-sql`, and `openrewrite/rewrite-templating`:\n\n- Anonymous class body containing multiple methods whose bodies return\n[…]\nenrewrite/rewrite-analysis`. The\nKotlin test ends up replacing `Stack` with `Deque` because the function only\nreturns the boolean, not the stack — so we just assert that the recipe runs\nto completion.",
          "is_bot": false,
          "headline": "Add regression tests for `ReplaceStackWithDeque` against `ControlFlow…",
          "author_name": "Knut Wannheden",
          "author_login": "knutwannheden",
          "committed_at": "2026-05-06T08:41:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "095656ff1597a05aa8fad91a5afcf5a3288c466f",
          "body": "… (#875)\n\nThe recipe previously transformed `() -> field != null` into\n`Objects::nonNull` even when the lambda had no parameter or the null\ncheck referred to a captured field rather than the lambda parameter,\nproducing code that no longer compiled.",
          "is_bot": false,
          "headline": "Skip `Objects::nonNull`/`isNull` when lambda parameter does not match…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-05T22:34:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "209f642ee7f8df7c7e7000060dba7f740aebc18a",
          "body": "* Preserve `(Object)` bridge cast for unchecked generic casts\n\nWhen a cast is wrapped by another cast and neither the outer cast type\nnor the inner expression type are assignable to one another, the inner\ncast is acting as a bridge for an unchecked generic conversion (e.g.\n`(List<String>) (Object) v\n[…]\n cast, primitive widen-then-narrow, controlling overload\nresolution — so just preserve. Also skip both `J.Parentheses` and\n`J.ControlParentheses` when walking up so parenthesized variants are\ncovered.",
          "is_bot": false,
          "headline": "Preserve `(Object)` bridge cast for unchecked generic casts (#876)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-05T16:30:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d2bf70305b2e6ec251d2323374ac4c68ce7d1369",
          "body": "Without the cast, calls like `<T extends SourceFile> T withSourcePath(Path)`\ninside a lambda lose `T` to its bound during outer inference (e.g.\n`Optional.map(...).ifPresent(generated::add)`), causing compilation errors.\n\nFixes #871",
          "is_bot": false,
          "headline": "Preserve casts pinning generic-method return type in lambdas (#872)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-04T09:10:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9f0285237c56af092bfa0fa69a98aa8c8e021bda",
          "body": null,
          "is_bot": false,
          "headline": "Use rewrite-java-21 for test runtime (#870)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-05-01T13:31:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "30a60ba05420d299cc94cd4fcf334c8101094404",
          "body": "* OpenRewrite recipe best practices\n\nUse this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.recipes.rewrite.OpenRewriteRecipeBestPractices?organizationId=QUxML01vZGVybmUvTW9kZXJuZSArIE9wZW5SZXdyaXRl\n\nCo-authored-by: Moderne <team@moderne.io>\n\n* Use rewrite-java-25 test ru\n[…]\nintroduced `_ ->` broke `compileTestJava`. Revert those two lambda\nparameters back to `cu ->` and bump the test runtime parser to\nrewrite-java-25.\n\n---------\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "OpenRewrite recipe best practices (#869)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-30T13:47:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "98d350e9a56c024a6fc7700fbe09bddadc956328",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.recipes.rewrite.OpenRewriteRecipeBestPractices?organizationId=QUxML01vZGVybmUvTW9kZXJuZSArIE9wZW5SZXdyaXRl\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "OpenRewrite recipe best practices",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-29T09:59:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d3e09e9fee25b62cf4d082539091c24db954910e",
          "body": "…ClassConstructor` (#867)\n\nEnables meta-annotation matching so classes annotated with `@TestConfiguration`,\n`@SpringBootApplication`, and any user-defined stereotype layered on top of\n`@Configuration` are also skipped.",
          "is_bot": false,
          "headline": "Skip meta-annotated `@Configuration` in `FinalClass` and `HideUtility…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-28T11:39:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ab8ff8d81a64366ec8c8f796cc82ab4e4f72d709",
          "body": "Refuse to merge a `close()` into try-with-resources when non-close\nstatements precede it in the finally block. Try-with-resources runs the\nauto-close before the finally, so those statements would otherwise move\nfrom before to after the close, changing semantics.",
          "is_bot": false,
          "headline": "Preserve statement order in `UseTryWithResources` (#866)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-28T10:53:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90e4a600e68fb164750c3f4e031db8e884d37108",
          "body": "…… (#865)\n\n* bugfix:  false positive in AnnotateNullableParameters when parameter is dereferenced before null check\n\n* Check all arguments for null-checked parameters\n\nAddresses review feedback: custom null-checkers may accept the parameter in a position other than first (e.g., `assertNotNull(message, param)`).\n\n---------\n\nCo-authored-by: stefanod <stefano.dallapalma@adyen.com>\nCo-authored-by: Tim te Beek <tim@moderne.io>",
          "is_bot": false,
          "headline": "bugfix:  false positive in AnnotateNullableParameters when parameter …",
          "author_name": "Stefano Dalla Palma",
          "author_login": "stefanodallapalma",
          "committed_at": "2026-04-23T19:22:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b315bbcda4429a590a4ec4a9677706446da88f0f",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.java.recipes.ExamplesExtractor?organizationId=QUxML09wZW4gU291cmNlL09wZW5SZXdyaXRl\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "Extract documentation examples from tests",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-04-21T07:05:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9ba38b4c9ad206562efc3d18fb0457ba379cd560",
          "body": "…ent (#864)\n\nCovers the dataflow crash fixed in openrewrite/rewrite-analysis#95,\nwhere the recipe threw `Unable to create DataFlowNode` when a `Stack`\nvariable shared a method with a call that passed `this` as an argument.",
          "is_bot": false,
          "headline": "Add regression test for `ReplaceStackWithDeque` crash on `this` argum…",
          "author_name": "Knut Wannheden",
          "author_login": "knutwannheden",
          "committed_at": "2026-04-21T06:48:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "78afc2590d0bfb63657e7f023eb0569b29ee8af2",
          "body": "…a lambda initializer (#862)\n\nSkip private fields whose only assignment is in the constructor body when they\nare read inside a lambda or anonymous class in an instance field initializer or\ninstance initializer block. Since initializers run before the constructor body,\nfinalizing such fields breaks javac's definite assignment analysis.\n\nFixes #861",
          "is_bot": false,
          "headline": "Fix FinalizePrivateFields breaking compilation when field is read in …",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-17T13:04:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3b2d84764c295a44ef84656fa925e302194aca86",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.recipes.rewrite.OpenRewriteRecipeBestPractices?organizationId=QUxML01vZGVybmUvTW9kZXJuZSArIE9wZW5SZXdyaXRl\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "OpenRewrite recipe best practices",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-17T11:01:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a0baac34f3445652b24b4dea6e428d8cc6719eb",
          "body": "…es close() (#863)\n\nWhen a try-catch contains a nested try-with-resources, the outer catch may\nhandle exceptions thrown by the resource's close() method. The visitor now\ncollects those exceptions so the outer catch is preserved.\n\nFixes #677",
          "is_bot": false,
          "headline": "Fix UnnecessaryCatch removing IOException for nested try-with-resourc…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-17T09:05:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "47094c2f1f455cd26fcbddb5cc823010b5fd20bf",
          "body": "* Handle chained addition in PreferIncrementOperator\n\nCloses #696\n\nWalk the left spine of binary +/- expressions to find the assigned\nvariable as the leftmost operand, enabling transformations like\n`x = x + a + b + 1` → `x += a + b + 1`.\n\n* Regenerate recipes.csv\n\n---------\n\nCo-authored-by: Tim te Beek <tim@moderne.io>",
          "is_bot": false,
          "headline": "Handle chained addition in PreferIncrementOperator (#816)",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-04-17T09:01:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e097fabe401e6fc226cd76721d2007e6c3f34ab1",
          "body": null,
          "is_bot": false,
          "headline": "Add tests confirming #20 is fixed (#860)",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-04-16T09:39:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3710118f705c1a74925dfc989b48edf014dbfdb9",
          "body": null,
          "is_bot": false,
          "headline": "Test for if-else, fix do-while NeedBraces (#859)",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-04-16T09:12:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c6ebfd47840eb53d792ebe6f153676be1942363b",
          "body": "* Add S1185 recipe: Remove methods that only call super\n\nImplements RSPEC-S1185 to detect and remove methods that override a parent\nmethod but only delegate to super with the same arguments. Includes 12\ncomprehensive test cases covering positive and negative scenarios.\n\n* Simplify argumentsMatchPara\n[…]\n @Transactional retention test\n\nRemove removeMethodWithOnlyOverrideAnnotation which duplicated existing\ncoverage. Add test verifying methods with semantic annotations like\n@Transactional are retained.",
          "is_bot": false,
          "headline": "Add S1185 recipe: Remove methods that only call super (#837)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-15T14:22:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e9d90e732ac1c227013b0657f375cd41d9776983",
          "body": "* Add S2209/S3252 recipe: Static members should be accessed via class name\n\nImplements OpenRewrite recipe to replace static field/method access through instance references with access via the declaring class name. Transforms instance.staticField to ClassName.staticField and instance.staticMethod() t\n[…]\nted class handling with the existing utility,\nwhich correctly handles type attribution, parameterized types, and\nlocal classes.\n\n* Add inner class and anonymous class tests for StaticAccessViaInstance",
          "is_bot": false,
          "headline": "Add S2209/S3252 recipe: Static members via class name (#836)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-13T22:27:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ee4199a5dde3f97d669629e4be417c6381efdd93",
          "body": "* Add RemoveUnusedLabels recipe (RSPEC-S1065)\n\nRemove labels that are not referenced by any break or continue statement. The labeled statement is preserved, with the label removed.\n\nIncludes 6 test cases covering unused labels on loops and blocks, labels referenced by break/continue, and partial rem\n[…]\nenarios.\n\n* Update recipes.csv with RemoveUnusedLabels entry\n\n* Use idiomatic reduce() pattern for subtree scanning\n\n* Move @Getter to class level; invert if condition\n\n* Update copyright year to 2026",
          "is_bot": false,
          "headline": "Add RemoveUnusedLabels recipe (RSPEC-S1065) (#835)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-13T15:53:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "df3a60bce33e4ea8e29adb1e91a582e6fa393f1b",
          "body": "* Add SillyEqualsCheck recipe (RSPEC-S2159)\n\nImplements SonarQube rule S2159: detects `.equals()` calls that always return false due to incompatible types. The recipe transforms:\n- `x.equals(null)` → `x == null` (with negation handling)\n- `arr1.equals(arr2)` → `Arrays.equals(arr1, arr2)` for arrays\n\n[…]\ncursor walk through J.Parentheses nodes. This\ncannot throw on unlisted AST contexts.\n\n* Remove redundant @Getter annotations implied by @Value\n\n* Use J.Literal.isLiteralValue(arg, null) for null check",
          "is_bot": false,
          "headline": "Add SillyEqualsCheck recipe (RSPEC-S2159) (#834)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-13T15:53:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e59af63412317c010d396cc39ec51192bb31c3c2",
          "body": "…(#858)\n\n* Fix UnnecessaryExplicitTypeArguments within lambda return statements (#670)\n\n* Extract findMethodIfUnambiguous and getLambdaReturnType methods",
          "is_bot": false,
          "headline": "Fix UnnecessaryExplicitTypeArguments within lambda return statements …",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-13T10:29:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "58455164cd5ce54151529b5aaa50837dabfa9ee5",
          "body": "… (#857)\n\n* Fix FinalizeLocalVariables crash on Kotlin/Groovy top-level variables (#702)\n\n* Merge Kotlin/Groovy tests into main FinalizeLocalVariablesTest",
          "is_bot": false,
          "headline": "Fix FinalizeLocalVariables crash on Kotlin/Groovy top-level variables…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-12T19:41:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8686b01d7198c984740ec012e675c0765e302516",
          "body": "…#856)",
          "is_bot": false,
          "headline": "Fix RenameExceptionInEmptyCatch crash on Kotlin/Groovy files (#701) (…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-12T19:31:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cbc1692de925ef8138291005cb6b856820e0f0f3",
          "body": "… scoping (#855)\n\n* Fix InstanceOfPatternMatch duplicate pattern variable names with flow scoping\n\nTrack introduced pattern variable names across statements within a method\nto avoid generating duplicates when Java's flow scoping keeps an earlier\npattern variable in scope (e.g., else branch with retu\n[…]\n\n* Add ROOT_VALUE guard and extract trackIntroducedName helper\n\nAdd Cursor.ROOT_VALUE to dropParentUntil predicate for safety, and\ndeduplicate the pattern variable tracking logic into a helper method.",
          "is_bot": false,
          "headline": "Fix InstanceOfPatternMatch duplicate pattern variable names with flow…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-12T13:07:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "77719d2d8834629dacdf89eaf66c0b8c6ed47c91",
          "body": "* Add recipe to enforce space after // in single-line comments\n\n* fix review comments\n\n* Use ListUtils.map as suggested by reviewer\n\n* fix review comments: use @Getter fields, skip block comments, update copyright year\n\n* Invert instanceof check and combine with isMultiline guard\n\n* Skip noinspection and region/endregion IDE comments\n\n---------\n\nCo-authored-by: Tim te Beek <tim@moderne.io>",
          "is_bot": false,
          "headline": "Add space after // in single-line comments (#854)",
          "author_name": "Avimta Likhitkar",
          "author_login": "avimta",
          "committed_at": "2026-04-11T12:58:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e51f2b46bbadc70f8d65effc4085b7e8ae4939ec",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.recipes.rewrite.OpenRewriteRecipeBestPractices?organizationId=QUxML01vZGVybmUvTW9kZXJuZSArIE9wZW5SZXdyaXRl\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "OpenRewrite recipe best practices",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-10T08:00:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2f72e68392286f0d87db97ccdbdbed5cc714c8e4",
          "body": "- FallThrough: don't add breaks inside nested switch expressions (#14)\n- MinimumSwitchCases: preserve comments from default case (#6)\n- MinimumSwitchCases: redeclare variables in else blocks (#687)\n- InlineVariable: add test confirming enum arrays are not inlined (#9)",
          "is_bot": false,
          "headline": "Fix switch-related recipe bugs (#6, #9, #14, #687) (#852)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-09T12:23:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "92a5960205d1d4e928292138f042db760598c466",
          "body": "…on tests (#851)\n\n* Fix EmptyBlock, FinalClass, HideUtilityClassConstructor and add regression tests\n\n- EmptyBlock: stop adding unnecessary `continue;` to empty while/do-while loops (#570)\n- FinalClass: skip classes annotated with @Configuration (#729)\n- HideUtilityClassConstructor: skip @Configuration classes (#729)\n- Add regression tests for #7, #221 confirming they are already fixed\n\n* Remove unused loop visitor methods\n\nRemoved unused visitWhileLoop and visitDoWhileLoop methods.",
          "is_bot": false,
          "headline": "Fix EmptyBlock, FinalClass, HideUtilityClassConstructor; add regressi…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-09T12:19:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "421c07ef3de89b3f159fb5db16a675692da8408e",
          "body": "* Enrich recipe descriptions with \"why\" rationale for RSPEC-tagged rules\n\nThe RSPEC tags on static analysis recipes used to link to SonarSource's\npublic rule documentation, but those URLs have been decommissioned.\nRather than adding broken links, this enriches each recipe's description\nfield with 1-\n[…]\n the\nrecipes self-documenting. Descriptions for 98 recipes were updated;\n9 were skipped because they already had thorough rationale.\n\n* Reformat description strings to wrap at ~120 characters per line",
          "is_bot": false,
          "headline": "Enrich recipe descriptions with rationale (#850)",
          "author_name": "Jonathan Schnéider",
          "author_login": "jkschneider",
          "committed_at": "2026-04-08T23:22:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c02f72d04f59fed8619b8921a6caebfb84797fef",
          "body": "…ons pointing to itself (#849)\n\n* Avoid invalid x=x variable declarations\n\n* A more involved case\n\n* Order of clauses shouldn't decide",
          "is_bot": false,
          "headline": "`InstanceOfPatternMatch` to avoid providing invalid variable definiti…",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-04-08T19:05:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1b97fad6812098e73f10e8be6d112d2fec5478bf",
          "body": null,
          "is_bot": false,
          "headline": "Test for issue 276 (#848)",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-04-08T18:33:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "901ba810cf2b9822d93975e2c712fba77567ac76",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.recipes.rewrite.OpenRewriteRecipeBestPractices?organizationId=QUxML01vZGVybmUvTW9kZXJuZSArIE9wZW5SZXdyaXRl\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "OpenRewrite recipe best practices",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-08T08:21:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "927f25ddd3c48144a67aebd3c286e514e7a4ab49",
          "body": null,
          "is_bot": false,
          "headline": "Skip `InstanceOfPatternMatch` for try-with-resources casts (#847)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-04-07T11:57:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ded8a7c8f826d5a6cb2050987127b86b2a39ef0",
          "body": "…notation placement issues (#845)\n\n* fix annotations duplication and position\n\n* Align nullable detection with AnnotateNullableParameters\n\n- Replace NULLABLE_ANNOTATION_SIMPLE_NAMES set with case-insensitive\n  contains(\"null\") check to handle custom annotations (e.g. @NullAllowed)\n- Replace NON_TYPE\n[…]\nbleParameters\n- Update tests to expect custom/unknown annotations as declaration-target\n\n---------\n\nCo-authored-by: stefanod <stefano.dallapalma@adyen.com>\nCo-authored-by: Tim te Beek <tim@moderne.io>",
          "is_bot": false,
          "headline": "Improve AnnotateNullableMethods to avoid duplicate annotations and an…",
          "author_name": "Stefano Dalla Palma",
          "author_login": "stefanodallapalma",
          "committed_at": "2026-04-01T09:46:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c6a7799a9818adcaeab2c09987a5186766171928",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.java.recipes.UseJavaTemplateStaticApply?organizationId=QUxML01vZGVybmUvTW9kZXJuZSArIE9wZW5SZXdyaXRl\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "Use `JavaTemplate.apply()` static method (#846)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-03-31T19:03:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "78f9ddce1bf80477da448252d70f5a7eb2cf8d66",
          "body": "Replace stored JavaTemplate fields with inline builder chains across 8\nrecipes, eliminating unnecessary visitor state.",
          "is_bot": false,
          "headline": "Inline JavaTemplate fields at call sites (#844)",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-03-31T16:04:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3f3cd50a7c676b71855624e652347aca7ba992c5",
          "body": "… annotation placement issues (#843)\n\n* fix duplicate nullable annotations\n\nfix annotation position\n\n* Replace known nullable annotations list with simple name matching\n\nInstead of maintaining a hardcoded list of 13 nullable annotation FQNs,\ndetect any annotation whose simple name contains \"null\" (c\n[…]\n duplication/conflicts.\n\n* Use .reduce for immediate return in hasNullRelatedAnnotation\n\n---------\n\nCo-authored-by: stefanod <stefano.dallapalma@adyen.com>\nCo-authored-by: Tim te Beek <tim@moderne.io>",
          "is_bot": false,
          "headline": "Improve AnnotateNullableParameters to avoid duplicate annotations and…",
          "author_name": "Stefano Dalla Palma",
          "author_login": "stefanodallapalma",
          "committed_at": "2026-03-31T11:58:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0a3f00142638a87cb53e2b291147b437a3dfebd9",
          "body": null,
          "is_bot": false,
          "headline": "Fix compilation after new args to Cs.CompilationUnit (#842)",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-03-26T19:18:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0d114b7f08e4917d9f8d260328ac9e53e51b1954",
          "body": null,
          "is_bot": false,
          "headline": "No longer expected to fail (#841)",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-03-26T08:18:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "941c8431cf6e3f0d00a785a23bbc46baf81eb325",
          "body": null,
          "is_bot": false,
          "headline": "Remove @Disabled tests (#840)",
          "author_name": "Greg Oledzki",
          "author_login": "greg-at-moderne",
          "committed_at": "2026-03-25T14:40:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c82f961b43fa48611e1931bf499d9b6d3033c34d",
          "body": "…n (#839)\n\n* SimplifyBooleanExpression: don't simplify nullable boolean comparisons in Kotlin\n\nThe `shouldSimplifyEqualsOn` override previously only checked for the\n`IsNullSafe` marker on method invocations (e.g. `x?.fun() == true`), but\nmissed plain nullable boolean comparisons like `nullableBoolea\n[…]\n comparisons.\n\nFixes #303\n\n* SimplifyBooleanExpression: delegate to super.shouldSimplifyEqualsOn for Java files\n\n* Apply suggestions from code review\n\nCo-authored-by: Tim te Beek <timtebeek@gmail.com>",
          "is_bot": false,
          "headline": "SimplifyBooleanExpression: skip nullable boolean comparisons in Kotli…",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-03-24T10:17:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "879b179ea0bb3ca760c2205ccf9ed93db7109fd9",
          "body": "Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.recipes.rewrite.OpenRewriteRecipeBestPractices?organizationId=QUxML01vZGVybmUvTW9kZXJuZSArIE9wZW5SZXdyaXRl\n\nCo-authored-by: Moderne <team@moderne.io>",
          "is_bot": false,
          "headline": "OpenRewrite recipe best practices",
          "author_name": "Tim te Beek",
          "author_login": "timtebeek",
          "committed_at": "2026-03-23T08:56:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5d7e7b1abb82cbd6e65a7f2d68fd86f03673e1e3",
          "body": "* Add ExplicitThis recipe to make 'this.' prefix explicit.\n\n* Simplify ExplicitThis recipe using existing utilities\n\n- Replace magic number 0x0008L with hasFlags(Flag.Static) and hasModifier()\n- Use JavaElementFactory.newThis() instead of manual identifier construction\n- Use TypeUtils.isOfType() for\n[…]\nlight polish\n\n* Add a test to check for shadowing of variables\n\n* Slight polish\n\n* Update docs\n\n---------\n\nCo-authored-by: Tim te Beek <tim@moderne.io>\nCo-authored-by: Knut Wannheden <knut@moderne.io>",
          "is_bot": false,
          "headline": "Add ExplicitThis recipe to make `this.` prefix explicit. (#791)",
          "author_name": "Craig P. Motlin",
          "author_login": "motlin",
          "committed_at": "2026-03-21T22:16:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        }
      ],
      "releases_count": 91,
      "commits_last_year": 253,
      "latest_release_at": "2026-07-14T05:34:02Z",
      "latest_release_tag": "v2.39.0",
      "releases_from_tags": false,
      "days_since_last_push": 1,
      "active_weeks_last_year": 47,
      "days_since_latest_release": 11,
      "mean_days_between_releases": 10.7
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 75,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": []
    },
    "popularity": {
      "forks": 102,
      "stars": 58,
      "watchers": 7,
      "fork_history": {
        "days": [
          {
            "date": "2023-05-03",
            "count": 1
          },
          {
            "date": "2023-05-06",
            "count": 2
          },
          {
            "date": "2023-05-09",
            "count": 1
          },
          {
            "date": "2023-05-17",
            "count": 1
          },
          {
            "date": "2023-05-21",
            "count": 1
          },
          {
            "date": "2023-05-26",
            "count": 1
          },
          {
            "date": "2023-05-27",
            "count": 1
          },
          {
            "date": "2023-06-06",
            "count": 1
          },
          {
            "date": "2023-06-13",
            "count": 1
          },
          {
            "date": "2023-06-19",
            "count": 1
          },
          {
            "date": "2023-06-29",
            "count": 1
          },
          {
            "date": "2023-06-30",
            "count": 1
          },
          {
            "date": "2023-08-10",
            "count": 1
          },
          {
            "date": "2023-09-27",
            "count": 1
          },
          {
            "date": "2023-10-02",
            "count": 1
          },
          {
            "date": "2023-10-03",
            "count": 1
          },
          {
            "date": "2023-10-13",
            "count": 1
          },
          {
            "date": "2023-10-14",
            "count": 1
          },
          {
            "date": "2023-10-16",
            "count": 1
          },
          {
            "date": "2023-11-02",
            "count": 1
          },
          {
            "date": "2023-11-16",
            "count": 1
          },
          {
            "date": "2023-12-30",
            "count": 1
          },
          {
            "date": "2023-12-31",
            "count": 1
          },
          {
            "date": "2024-01-10",
            "count": 1
          },
          {
            "date": "2024-01-15",
            "count": 1
          },
          {
            "date": "2024-01-17",
            "count": 1
          },
          {
            "date": "2024-01-20",
            "count": 1
          },
          {
            "date": "2024-01-21",
            "count": 1
          },
          {
            "date": "2024-01-22",
            "count": 1
          },
          {
            "date": "2024-01-28",
            "count": 1
          },
          {
            "date": "2024-02-17",
            "count": 1
          },
          {
            "date": "2024-03-10",
            "count": 1
          },
          {
            "date": "2024-03-18",
            "count": 1
          },
          {
            "date": "2024-05-11",
            "count": 1
          },
          {
            "date": "2024-05-13",
            "count": 1
          },
          {
            "date": "2024-05-19",
            "count": 1
          },
          {
            "date": "2024-06-13",
            "count": 1
          },
          {
            "date": "2024-06-29",
            "count": 1
          },
          {
            "date": "2024-07-04",
            "count": 2
          },
          {
            "date": "2024-08-20",
            "count": 1
          },
          {
            "date": "2024-10-01",
            "count": 1
          },
          {
            "date": "2024-10-02",
            "count": 1
          },
          {
            "date": "2024-10-12",
            "count": 1
          },
          {
            "date": "2024-10-14",
            "count": 1
          },
          {
            "date": "2024-10-18",
            "count": 1
          },
          {
            "date": "2024-10-30",
            "count": 1
          },
          {
            "date": "2024-11-17",
            "count": 1
          },
          {
            "date": "2024-11-25",
            "count": 1
          },
          {
            "date": "2024-12-03",
            "count": 1
          },
          {
            "date": "2024-12-21",
            "count": 1
          },
          {
            "date": "2024-12-23",
            "count": 1
          },
          {
            "date": "2025-01-13",
            "count": 1
          },
          {
            "date": "2025-01-24",
            "count": 2
          },
          {
            "date": "2025-02-07",
            "count": 1
          },
          {
            "date": "2025-03-25",
            "count": 1
          },
          {
            "date": "2025-03-29",
            "count": 1
          },
          {
            "date": "2025-04-08",
            "count": 1
          },
          {
            "date": "2025-04-27",
            "count": 1
          },
          {
            "date": "2025-05-04",
            "count": 1
          },
          {
            "date": "2025-05-05",
            "count": 1
          },
          {
            "date": "2025-05-07",
            "count": 1
          },
          {
            "date": "2025-05-15",
            "count": 1
          },
          {
            "date": "2025-05-19",
            "count": 1
          },
          {
            "date": "2025-05-26",
            "count": 1
          },
          {
            "date": "2025-05-28",
            "count": 1
          },
          {
            "date": "2025-05-29",
            "count": 1
          },
          {
            "date": "2025-06-03",
            "count": 1
          },
          {
            "date": "2025-06-08",
            "count": 1
          },
          {
            "date": "2025-06-16",
            "count": 1
          },
          {
            "date": "2025-06-18",
            "count": 1
          },
          {
            "date": "2025-06-19",
            "count": 2
          },
          {
            "date": "2025-07-07",
            "count": 1
          },
          {
            "date": "2025-07-10",
            "count": 1
          },
          {
            "date": "2025-07-17",
            "count": 1
          },
          {
            "date": "2025-07-19",
            "count": 1
          },
          {
            "date": "2025-07-20",
            "count": 1
          },
          {
            "date": "2025-07-25",
            "count": 1
          },
          {
            "date": "2025-08-04",
            "count": 1
          },
          {
            "date": "2025-08-11",
            "count": 1
          },
          {
            "date": "2025-08-28",
            "count": 1
          },
          {
            "date": "2025-10-26",
            "count": 1
          },
          {
            "date": "2025-11-02",
            "count": 1
          },
          {
            "date": "2025-11-09",
            "count": 1
          },
          {
            "date": "2025-11-20",
            "count": 1
          },
          {
            "date": "2025-11-26",
            "count": 1
          },
          {
            "date": "2026-01-04",
            "count": 1
          },
          {
            "date": "2026-03-23",
            "count": 1
          },
          {
            "date": "2026-04-10",
            "count": 1
          },
          {
            "date": "2026-04-16",
            "count": 1
          },
          {
            "date": "2026-05-20",
            "count": 1
          },
          {
            "date": "2026-06-12",
            "count": 1
          },
          {
            "date": "2026-07-01",
            "count": 1
          },
          {
            "date": "2026-07-10",
            "count": 1
          },
          {
            "date": "2026-07-16",
            "count": 1
          },
          {
            "date": "2026-07-17",
            "count": 1
          },
          {
            "date": "2026-07-19",
            "count": 1
          },
          {
            "date": "2026-07-21",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 101,
        "total_forks": 102
      },
      "star_history": null,
      "open_issues_and_prs": 122
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "build.gradle.kts"
      ],
      "largest_source_bytes": 88413,
      "source_files_sampled": 403,
      "oversized_source_files": 2,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 8599
    },
    "dependencies": {
      "manifests": [
        "build.gradle.kts"
      ],
      "advisories": {
        "error": "No resolved dependencies to assess",
        "scope": "repository_graph",
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "maven"
      ],
      "dependencies": [],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [],
        "collected": true,
        "truncated": false,
        "total_count": 0,
        "direct_count": 0,
        "indirect_count": 0
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 6,
        "merged_prs": 427,
        "open_issues": 116,
        "closed_ratio": 0.72,
        "closed_issues": 298,
        "closed_unmerged_prs": 81
      },
      "bus_factor": 4,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "timtebeek",
          "commits": 362,
          "avatar_url": "https://avatars.githubusercontent.com/u/1027334?v=4"
        },
        {
          "type": "User",
          "login": "knutwannheden",
          "commits": 240,
          "avatar_url": "https://avatars.githubusercontent.com/u/408765?v=4"
        },
        {
          "type": "User",
          "login": "jkschneider",
          "commits": 213,
          "avatar_url": "https://avatars.githubusercontent.com/u/1697736?v=4"
        },
        {
          "type": "User",
          "login": "pway99",
          "commits": 138,
          "avatar_url": "https://avatars.githubusercontent.com/u/22326988?v=4"
        },
        {
          "type": "User",
          "login": "sambsnyd",
          "commits": 101,
          "avatar_url": "https://avatars.githubusercontent.com/u/8549033?v=4"
        },
        {
          "type": "User",
          "login": "traceyyoshima",
          "commits": 91,
          "avatar_url": "https://avatars.githubusercontent.com/u/16889475?v=4"
        },
        {
          "type": "User",
          "login": "kunli2",
          "commits": 89,
          "avatar_url": "https://avatars.githubusercontent.com/u/122563761?v=4"
        },
        {
          "type": "User",
          "login": "aegershman",
          "commits": 74,
          "avatar_url": "https://avatars.githubusercontent.com/u/5619476?v=4"
        },
        {
          "type": "User",
          "login": "greg-at-moderne",
          "commits": 55,
          "avatar_url": "https://avatars.githubusercontent.com/u/192309513?v=4"
        },
        {
          "type": "User",
          "login": "tkvangorder",
          "commits": 24,
          "avatar_url": "https://avatars.githubusercontent.com/u/1878529?v=4"
        }
      ],
      "contributors_sampled": 98,
      "top_contributor_share": 0.217
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "publish.yml",
        "repository-backup.yml",
        "stale.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": true,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 9,
            "reason": "binaries present in source code",
            "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": 9,
            "reason": "21 out of 23 merged PRs checked by a CI test -- score normalized to 9",
            "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": 2,
            "reason": "Found 8/30 approved changesets -- score normalized to 2",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 22 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "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": 9,
            "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 11 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": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "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": "5545efa3f71cabfb1feeacb55c26ae55538488f5",
        "ran_at": "2026-07-25T17:21:03Z",
        "aggregate_score": 5.2,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-24T18:22:28Z",
      "oldest_open_prs": [
        {
          "number": 897,
          "created_at": "2026-05-20T13:36:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 931,
          "created_at": "2026-07-01T00:45:12Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 938,
          "created_at": "2026-07-13T13:59:08Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 944,
          "created_at": "2026-07-19T18:02:58Z",
          "last_comment_at": "2026-07-19T18:03:25Z",
          "last_comment_author": "kush2439p"
        },
        {
          "number": 945,
          "created_at": "2026-07-21T02:27:49Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 951,
          "created_at": "2026-07-25T06:05:43Z",
          "last_comment_at": "2026-07-25T08:25:54Z",
          "last_comment_author": "habiibullahm"
        }
      ],
      "last_merged_pr_at": "2026-07-23T19:32:48Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 67,
          "created_at": "2021-04-21T19:55:36Z",
          "last_comment_at": "2021-05-21T22:03:53Z",
          "last_comment_author": "traceyyoshima"
        },
        {
          "number": 66,
          "created_at": "2021-05-10T16:10:24Z",
          "last_comment_at": "2021-05-28T00:28:38Z",
          "last_comment_author": "traceyyoshima"
        },
        {
          "number": 387,
          "created_at": "2021-05-20T21:37:06Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 65,
          "created_at": "2021-07-20T04:18:41Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 64,
          "created_at": "2021-07-21T17:04:39Z",
          "last_comment_at": "2021-08-22T23:51:10Z",
          "last_comment_author": "jkschneider"
        },
        {
          "number": 63,
          "created_at": "2021-07-21T17:07:21Z",
          "last_comment_at": "2021-08-22T23:52:08Z",
          "last_comment_author": "jkschneider"
        },
        {
          "number": 62,
          "created_at": "2021-07-21T17:08:50Z",
          "last_comment_at": "2021-08-22T23:00:36Z",
          "last_comment_author": "sambsnyd"
        },
        {
          "number": 61,
          "created_at": "2021-07-21T17:09:36Z",
          "last_comment_at": "2021-08-22T23:51:32Z",
          "last_comment_author": "jkschneider"
        },
        {
          "number": 60,
          "created_at": "2021-07-21T17:45:14Z",
          "last_comment_at": "2021-08-23T17:45:02Z",
          "last_comment_author": "jkschneider"
        },
        {
          "number": 69,
          "created_at": "2022-04-01T14:23:54Z",
          "last_comment_at": "2022-04-02T03:02:52Z",
          "last_comment_author": "tkvangorder"
        },
        {
          "number": 59,
          "created_at": "2022-04-02T14:42:04Z",
          "last_comment_at": "2022-04-04T20:29:15Z",
          "last_comment_author": "tkvangorder"
        },
        {
          "number": 57,
          "created_at": "2022-04-04T00:36:44Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 56,
          "created_at": "2022-04-04T20:03:31Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 55,
          "created_at": "2022-04-05T20:41:18Z",
          "last_comment_at": "2022-04-06T17:26:23Z",
          "last_comment_author": "traceyyoshima"
        },
        {
          "number": 54,
          "created_at": "2022-04-05T20:44:07Z",
          "last_comment_at": "2022-04-14T05:25:17Z",
          "last_comment_author": "traceyyoshima"
        },
        {
          "number": 53,
          "created_at": "2022-04-07T20:31:37Z",
          "last_comment_at": "2022-04-14T05:23:18Z",
          "last_comment_author": "traceyyoshima"
        },
        {
          "number": 71,
          "created_at": "2022-04-08T03:05:40Z",
          "last_comment_at": "2022-04-12T03:15:01Z",
          "last_comment_author": "yeikel"
        },
        {
          "number": 72,
          "created_at": "2022-04-11T01:00:51Z",
          "last_comment_at": "2022-04-11T16:10:05Z",
          "last_comment_author": "tkvangorder"
        },
        {
          "number": 52,
          "created_at": "2022-04-11T16:19:15Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 74,
          "created_at": "2022-04-13T04:00:10Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/openrewrite/rewrite-static-analysis",
    "host": "github.com",
    "name": "rewrite-static-analysis",
    "owner": "openrewrite"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 72,
      "inputs": {
        "security": 52,
        "vitality": 98,
        "community": 60,
        "governance": 77,
        "engineering": 63
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 98,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "excellent",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 96,
            "inputs": {
              "commits_last_year": 253,
              "human_commit_share": 1,
              "days_since_last_push": 1,
              "active_weeks_last_year": 47
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "47/52 weeks with commits",
                "points": 32.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 47
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "253 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 253
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 11 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "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": 100,
            "inputs": {
              "releases_count": 91,
              "latest_release_tag": "v2.39.0",
              "releases_from_tags": false,
              "days_since_latest_release": 11,
              "mean_days_between_releases": 10.7
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "91 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 91
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 11 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 11
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~10.7 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 10.7
                    }
                  }
                ],
                "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": 1,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 1 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "moderate",
        "name": "Community & Adoption",
        "value": 60,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "moderate",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "forks": 102,
              "stars": 58,
              "watchers": 7,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "58 stars",
                "points": 28.5,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 58
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "102 forks",
                "points": 16.7,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 102
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "7 watchers",
                "points": 4.3,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 71,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file present, not a recognized license",
                "points": 16.9,
                "status": "partial",
                "details": [
                  {
                    "code": "license_custom",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "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": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "good",
        "name": "Sustainability & Governance",
        "value": 77,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "good",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "bus_factor": 4,
              "contributors_sampled": 98,
              "top_contributor_share": 0.217
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "4 contributor(s) cover half of all commits",
                "points": 43.2,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 22% of commits",
                "points": 17.6,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 22
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "98 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 98
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 22 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "moderate",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 69,
            "inputs": {
              "merged_prs": 427,
              "open_issues": 116,
              "closed_issues": 298,
              "issue_closed_ratio": 0.72,
              "closed_unmerged_prs": 81
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "72% of issues closed",
                "points": 33.7,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 72
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "427/508 decided PRs merged",
                "points": 32.2,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 427,
                      "decided": 508
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 8/30 approved changesets -- score normalized to 2",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "good",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 76,
            "inputs": {
              "followers": 984,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "openrewrite",
              "public_repos": 75,
              "account_age_days": 2341
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "984 followers of openrewrite",
                "points": 21.5,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 984,
                      "login": "openrewrite"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "75 public repos, account ~6 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 75
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 6
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 63,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 72,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": true,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "4 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "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": 6.4,
                "status": "met",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "21 out of 23 merged PRs checked by a CI test -- score normalized to 9",
                "points": 18,
                "status": "partial",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "topics": [
                "good-first-issue",
                "java",
                "static-analysis",
                "static-code-analysis",
                "openrewrite",
                "openrewrite-recipes"
              ],
              "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": "6 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 6
                    }
                  }
                ],
                "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": 52,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 52,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 5.2
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "binaries present in source code",
                "points": 6.8,
                "status": "partial",
                "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": "21 out of 23 merged PRs checked by a CI test -- score normalized to 9",
                "points": 2.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 8/30 approved changesets -- score normalized to 2",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 22 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "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.2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 11 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": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "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": 16
            },
            "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": "good",
        "name": "AI Readiness",
        "value": 73,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.91,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 8599
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "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": "91 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 91,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 53,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.01,
              "toolchain_manifests": [
                "build.gradle.kts"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "build.gradle.kts (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "build.gradle.kts"
                    }
                  }
                ],
                "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": "Java (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Java"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "dependency automation configured, none observed in the sampled commits",
                "points": 5,
                "status": "partial",
                "details": [
                  {
                    "code": "dependency_bot_config_only",
                    "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": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Java",
              "largest_source_bytes": 88413,
              "source_files_sampled": 403,
              "oversized_source_files": 2
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Java (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Java"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "2/403 source files over 60KB",
                "points": 54.7,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 403,
                      "oversized": 2
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "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": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-25T17:21:28.139405Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/o/openrewrite/rewrite-static-analysis.svg",
  "full_name": "openrewrite/rewrite-static-analysis",
  "license_state": "custom",
  "license_spdx": null
}

评分是信号,而非担保。 评分反映的是 GitHub 上公开可见的实践——不是代码审计,也不是安全保证。

缺失数据将被剔除并重新归一化权重,绝不按零分计。方法论已版本化并公开:指标 v1.13.0、模式 v0.27.0—— 完整方法论 · 指标知识库.

单项结果在整体记录中的位置: 汇总统计.