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

LegionIO / legion-llm

LLM gateway: tiered routing (local to frontier), mid-stream provider failover, and post-turn context curation, production-measured. Provider adapters are separate lex-llm-* gems.

RubyApache-2.0★ 2 星标⑂ 3 复刻始于 2026年3月在 GitHub 上查看 ↗

LegionIO/legion-llm 的健康指数为 100 分中的 68 分,处于「中等」区间。 其得分最高的类别是Engineering Quality(84/100),最低的是Community & Adoption(48/100)。 最近一次更新在今天。 近期的大部分工作由 1 位贡献者完成。

68
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

LegionIO组织
23 关注者199 个公开仓库始于 2018年12月

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布
RubyGemslegion-llm0.14.17-1410 天前

按类别列示的指标

活力

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

82良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 0 天前
13.2/36提交节奏 — 52 周中有 19 周有提交
18/18提交量 — 最近一年 1,119 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year1,119
human_commit_share1
days_since_last_push0
active_weeks_last_year19

发布纪律

90优秀
评分方式
27/27有发布版本 — 已发布 100 个发布版本
36/36发布时效 — 最近一次发布版本于 0 天前
27/27发布节奏 — 约每 4 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — Project has not signed or included provenance with any releases.
所用输入
releases_count100
latest_release_tagv0.14.17
releases_from_tags
days_since_latest_release0
mean_days_between_releases4

社区与采用

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

48存在风险 · 占总体的 18%
评分方式
0/60星标 — 2 个星标
2.5/25复刻 — 3 个复刻
0/15关注者 — 1 位关注者
所用输入
forks3
stars2
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

92优秀
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(Apache-2.0)
18/18CONTRIBUTING 指南
13.5/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
评分方式
47.2/80累计下载量 — rubygems 合计历史 34,511 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packageslegion-llm
dependents
ecosystemsrubygems
total_downloads34,511
monthly_downloads
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

62中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0.4/22.5提交分布 — 头号贡献者编写了 98% 的提交
5.4/13.5贡献者广度 — 4 位贡献者
6/10OpenSSF Scorecard:Contributors — project has 2 contributing companies or organizations -- score normalized to 6
所用输入
bus_factor1
contributors_sampled4
top_contributor_share0.981
评分方式
42.8/46.8议题解决 — 92% 的议题已关闭
36.3/38.3PR 接受 — 已裁定的 PR 中 95/100 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/6 approved changesets -- score normalized to 0
所用输入
merged_prs95
open_issues6
closed_issues65
issue_closed_ratio0.915
closed_unmerged_prs5
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
9.9/25所有者影响力 — LegionIO 有 23 位关注者
25/25既往记录 — 199 个公开仓库,账户约 7 年
所用输入
followers23
owner_typeOrganization
is_verified
owner_loginLegionIO
public_repos199
account_age_days2,778
评分方式
25/25已发布且可解析 — rubygems 上有 1 个软件包
35/35发布时效 — 最近一次发布于 0 天前
20/20版本历史 — 141 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packageslegion-llm
ecosystemsrubygems
any_deprecated
min_days_since_publish0

工程质量

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

84良好 · 占总体的 20%

工程实践

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

文档

85优秀
评分方式
30/30README
25/25文档目录
0/15文档 / 主页站点
10/10仓库描述
10/10主题标签 — 5 个主题标签
10/10Wiki
所用输入
topicsai, legion-core, legionio, llm, ruby
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

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

59中等 · 占总体的 16%

安全态势

59中等
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 6 out of 6 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/6 approved changesets -- score normalized to 0
1.5/2.5Contributors — project has 2 contributing companies or organizations -- score normalized to 6
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 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
5/5SAST — SAST tool is run on all commits
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate5.9
已排除计分(无数据或不适用):packaging。 其余权重已重新归一化。

AI 就绪度

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

58中等 · 占总体的 0%
评分方式
45/45代理指令 — AGENTS.md, CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 82 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.82
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes7,940
评分方式
0/18一条命令的引导启动
22/22自动化测试
11/11Lint / 格式化配置 — .rubocop.yml
0/11静态类型检查
0/10可复现环境
0/10已体现的代理实践 — 最近 100 次提交中没有代理编写的提交
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
toolchain_manifests
dependency_bot_commit_share0
评分方式
0/45可类型检查的代码 — Ruby,未配置类型检查
54.8/55可控的文件大小 — 采样的 495 个源文件中有 2 个超过 60KB
所用输入
primary_languageRuby
largest_source_bytes66,627
source_files_sampled495
oversized_source_files2

关键数据

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

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • No resolved dependencies carried a version and a supported ecosystem

更多细节

Star 与 Fork 历史 0 ★ / 3 ⇿
0Star
3Fork
2发布

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

12233312026-042026-042026-04
主版本 0次版本 0修订 2
OpenSSF Scorecard 5.9 / 10
5.9综合

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

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests6 out of 6 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/6 approved changesets -- score normalized to 0
6Contributorsproject has 2 contributing companies or organizations -- score normalized to 6
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 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
10SASTSAST tool is run on all commits
10Security-Policysecurity policy file detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
直接依赖 11
注册表软件包版本约束清单文件
RubyGemslegion-settingsGemfile
RubyGemsrack-test~> 2.0Gemfile
RubyGemsrakeGemfile
RubyGemsrspecGemfile
RubyGemsrspec_junit_formatterGemfile
RubyGemsrubocopGemfile
RubyGemsrubocop-legionGemfile
RubyGemsrubocop-legion>= 0.1.8Gemfile
RubyGemssimplecovGemfile
RubyGemssinatraGemfile
RubyGemswebmockGemfile
全部依赖 22

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

注册表软件包版本关系
RubyGemslegion-settings直接
RubyGemsrack-test直接
RubyGemsrake直接
RubyGemsrspec直接
RubyGemsrspec_junit_formatter直接
RubyGemsrubocop直接
RubyGemsrubocop-legion直接
RubyGemssimplecov直接
RubyGemssinatra直接
RubyGemswebmock直接
RubyGemsconcurrent-ruby间接
RubyGemsevent_stream_parser间接
RubyGemsfaraday间接
RubyGemslegion-cache间接
RubyGemslegion-json间接
RubyGemslegion-logging间接
RubyGemslegion-transport间接
RubyGemslex-knowledge间接
RubyGemslex-llm间接
RubyGemspdf-reader间接
RubyGemssinatra-contrib间接
RubyGemstzinfo间接
依赖安全公告 未评估

本报告未能完成公告比对:No resolved dependencies carried a version and a supported ecosystem

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "ai",
        "legion-core",
        "legionio",
        "llm",
        "ruby"
      ],
      "is_fork": false,
      "size_kb": 4872,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Ruby": 3290613,
        "Shell": 32188
      },
      "pushed_at": "2026-07-23T23:04:39Z",
      "created_at": "2026-03-13T06:44:16Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-23T23:03:53Z",
      "description": "LLM gateway: tiered routing (local to frontier), mid-stream provider failover, and post-turn context curation, production-measured. Provider adapters are separate lex-llm-* gems.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "Ruby",
      "significant_languages": [
        "Ruby"
      ]
    },
    "owner": {
      "blog": null,
      "name": "LegionIO",
      "type": "Organization",
      "login": "LegionIO",
      "company": null,
      "location": null,
      "followers": 23,
      "avatar_url": "https://avatars.githubusercontent.com/u/45882021?v=4",
      "created_at": "2018-12-14T17:37:00Z",
      "is_verified": null,
      "public_repos": 199,
      "account_age_days": 2778
    },
    "license": {
      "state": "standard",
      "spdx_id": "Apache-2.0",
      "raw_spdx": "Apache-2.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.14.17",
          "kind": "patch",
          "published_at": "2026-07-23T23:04:40Z"
        },
        {
          "tag": "v0.14.16",
          "kind": "patch",
          "published_at": "2026-07-15T05:17:33Z"
        },
        {
          "tag": "v0.14.15",
          "kind": "patch",
          "published_at": "2026-07-09T08:28:04Z"
        },
        {
          "tag": "v0.14.10",
          "kind": "patch",
          "published_at": "2026-06-26T07:39:03Z"
        },
        {
          "tag": "v0.14.9",
          "kind": "patch",
          "published_at": "2026-06-26T04:30:58Z"
        },
        {
          "tag": "v0.14.8",
          "kind": "patch",
          "published_at": "2026-06-26T01:37:03Z"
        },
        {
          "tag": "v0.14.4",
          "kind": "patch",
          "published_at": "2026-06-24T18:53:57Z"
        },
        {
          "tag": "v0.14.3",
          "kind": "patch",
          "published_at": "2026-06-23T08:52:52Z"
        },
        {
          "tag": "v0.14.2",
          "kind": "patch",
          "published_at": "2026-06-21T01:33:26Z"
        },
        {
          "tag": "v0.13.0",
          "kind": "minor",
          "published_at": "2026-06-17T20:19:56Z"
        },
        {
          "tag": "v0.12.14",
          "kind": "patch",
          "published_at": "2026-06-10T06:11:13Z"
        },
        {
          "tag": "v0.12.3",
          "kind": "patch",
          "published_at": "2026-06-03T03:55:44Z"
        },
        {
          "tag": "v0.12.2",
          "kind": "patch",
          "published_at": "2026-06-03T00:37:10Z"
        },
        {
          "tag": "v0.11.2",
          "kind": "patch",
          "published_at": "2026-06-02T08:47:57Z"
        },
        {
          "tag": "v0.10.2",
          "kind": "patch",
          "published_at": "2026-05-31T01:54:11Z"
        },
        {
          "tag": "v0.10.1",
          "kind": "patch",
          "published_at": "2026-05-30T06:01:53Z"
        },
        {
          "tag": "v0.9.54",
          "kind": "patch",
          "published_at": "2026-05-29T19:17:02Z"
        },
        {
          "tag": "v0.9.53",
          "kind": "patch",
          "published_at": "2026-05-29T18:38:37Z"
        },
        {
          "tag": "v0.9.52",
          "kind": "patch",
          "published_at": "2026-05-27T14:57:35Z"
        },
        {
          "tag": "v0.9.51",
          "kind": "patch",
          "published_at": "2026-05-23T22:27:16Z"
        },
        {
          "tag": "v0.9.37",
          "kind": "patch",
          "published_at": "2026-05-22T10:05:09Z"
        },
        {
          "tag": "v0.9.36",
          "kind": "patch",
          "published_at": "2026-05-22T09:27:50Z"
        },
        {
          "tag": "v0.9.35",
          "kind": "patch",
          "published_at": "2026-05-22T08:51:08Z"
        },
        {
          "tag": "v0.9.34",
          "kind": "patch",
          "published_at": "2026-05-22T07:45:55Z"
        },
        {
          "tag": "v0.9.33",
          "kind": "patch",
          "published_at": "2026-05-22T07:14:34Z"
        },
        {
          "tag": "v0.9.32",
          "kind": "patch",
          "published_at": "2026-05-19T07:22:06Z"
        },
        {
          "tag": "v0.9.30",
          "kind": "patch",
          "published_at": "2026-05-17T15:48:35Z"
        },
        {
          "tag": "v0.9.29",
          "kind": "patch",
          "published_at": "2026-05-16T19:42:28Z"
        },
        {
          "tag": "v0.9.28",
          "kind": "patch",
          "published_at": "2026-05-15T23:07:50Z"
        },
        {
          "tag": "v0.9.23",
          "kind": "patch",
          "published_at": "2026-05-13T21:15:11Z"
        },
        {
          "tag": "v0.9.22",
          "kind": "patch",
          "published_at": "2026-05-13T05:32:45Z"
        },
        {
          "tag": "v0.9.19",
          "kind": "patch",
          "published_at": "2026-05-12T06:18:04Z"
        },
        {
          "tag": "v0.9.17",
          "kind": "patch",
          "published_at": "2026-05-11T22:40:04Z"
        },
        {
          "tag": "v0.9.15",
          "kind": "patch",
          "published_at": "2026-05-08T09:54:56Z"
        },
        {
          "tag": "v0.9.14",
          "kind": "patch",
          "published_at": "2026-05-08T02:46:00Z"
        },
        {
          "tag": "v0.9.10",
          "kind": "patch",
          "published_at": "2026-05-07T19:15:34Z"
        },
        {
          "tag": "v0.9.9",
          "kind": "patch",
          "published_at": "2026-05-07T05:35:06Z"
        },
        {
          "tag": "v0.8.49",
          "kind": "patch",
          "published_at": "2026-05-05T15:21:38Z"
        },
        {
          "tag": "v0.8.47",
          "kind": "patch",
          "published_at": "2026-04-29T22:02:42Z"
        },
        {
          "tag": "v0.8.32",
          "kind": "patch",
          "published_at": "2026-04-27T22:38:31Z"
        },
        {
          "tag": "v0.8.30",
          "kind": "patch",
          "published_at": "2026-04-27T18:49:50Z"
        },
        {
          "tag": "v0.8.29",
          "kind": "patch",
          "published_at": "2026-04-27T15:29:47Z"
        },
        {
          "tag": "v0.8.28",
          "kind": "patch",
          "published_at": "2026-04-25T20:42:59Z"
        },
        {
          "tag": "v0.8.27",
          "kind": "patch",
          "published_at": "2026-04-24T07:58:15Z"
        },
        {
          "tag": "v0.8.26",
          "kind": "patch",
          "published_at": "2026-04-24T06:55:35Z"
        },
        {
          "tag": "v0.8.25",
          "kind": "patch",
          "published_at": "2026-04-24T06:01:05Z"
        },
        {
          "tag": "v0.8.24",
          "kind": "patch",
          "published_at": "2026-04-23T15:06:12Z"
        },
        {
          "tag": "v0.8.23",
          "kind": "patch",
          "published_at": "2026-04-23T05:55:00Z"
        },
        {
          "tag": "v0.8.22",
          "kind": "patch",
          "published_at": "2026-04-23T05:20:47Z"
        },
        {
          "tag": "v0.8.21",
          "kind": "patch",
          "published_at": "2026-04-23T05:06:34Z"
        },
        {
          "tag": "v0.8.19",
          "kind": "patch",
          "published_at": "2026-04-23T04:10:38Z"
        },
        {
          "tag": "v0.8.18",
          "kind": "patch",
          "published_at": "2026-04-23T02:50:39Z"
        },
        {
          "tag": "v0.8.15",
          "kind": "patch",
          "published_at": "2026-04-22T23:16:57Z"
        },
        {
          "tag": "v0.8.3",
          "kind": "patch",
          "published_at": "2026-04-22T17:23:36Z"
        },
        {
          "tag": "v0.8.2",
          "kind": "patch",
          "published_at": "2026-04-22T15:29:56Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-04-22T07:25:28Z"
        },
        {
          "tag": "v0.7.15",
          "kind": "patch",
          "published_at": "2026-04-20T17:47:37Z"
        },
        {
          "tag": "v0.7.8",
          "kind": "patch",
          "published_at": "2026-04-17T01:06:34Z"
        },
        {
          "tag": "v0.7.7",
          "kind": "patch",
          "published_at": "2026-04-16T15:11:55Z"
        },
        {
          "tag": "v0.7.6",
          "kind": "patch",
          "published_at": "2026-04-14T01:35:46Z"
        },
        {
          "tag": "v0.7.5",
          "kind": "patch",
          "published_at": "2026-04-14T01:22:28Z"
        },
        {
          "tag": "v0.7.4",
          "kind": "patch",
          "published_at": "2026-04-14T00:40:25Z"
        },
        {
          "tag": "v0.7.3",
          "kind": "patch",
          "published_at": "2026-04-13T23:22:37Z"
        },
        {
          "tag": "v0.7.2",
          "kind": "patch",
          "published_at": "2026-04-13T17:33:35Z"
        },
        {
          "tag": "v0.7.1",
          "kind": "patch",
          "published_at": "2026-04-13T17:07:16Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-04-13T00:57:52Z"
        },
        {
          "tag": "v0.6.31",
          "kind": "patch",
          "published_at": "2026-04-10T17:58:31Z"
        },
        {
          "tag": "v0.6.30",
          "kind": "patch",
          "published_at": "2026-04-10T14:53:43Z"
        },
        {
          "tag": "v0.6.29",
          "kind": "patch",
          "published_at": "2026-04-09T23:14:33Z"
        },
        {
          "tag": "v0.6.28",
          "kind": "patch",
          "published_at": "2026-04-09T22:46:57Z"
        },
        {
          "tag": "v0.6.27",
          "kind": "patch",
          "published_at": "2026-04-09T19:19:26Z"
        },
        {
          "tag": "v0.6.26",
          "kind": "patch",
          "published_at": "2026-04-09T16:14:18Z"
        },
        {
          "tag": "v0.6.25",
          "kind": "patch",
          "published_at": "2026-04-09T04:34:12Z"
        },
        {
          "tag": "v0.6.24",
          "kind": "patch",
          "published_at": "2026-04-08T05:58:59Z"
        },
        {
          "tag": "v0.6.23",
          "kind": "patch",
          "published_at": "2026-04-07T06:14:05Z"
        },
        {
          "tag": "v0.6.20",
          "kind": "patch",
          "published_at": "2026-04-07T04:20:13Z"
        },
        {
          "tag": "v0.6.18",
          "kind": "patch",
          "published_at": "2026-04-06T23:53:03Z"
        },
        {
          "tag": "v0.6.17",
          "kind": "patch",
          "published_at": "2026-04-06T20:58:50Z"
        },
        {
          "tag": "v0.6.16",
          "kind": "patch",
          "published_at": "2026-04-03T21:36:08Z"
        },
        {
          "tag": "v0.6.15",
          "kind": "patch",
          "published_at": "2026-04-03T19:30:18Z"
        },
        {
          "tag": "v0.6.14",
          "kind": "patch",
          "published_at": "2026-04-03T04:56:54Z"
        },
        {
          "tag": "v0.6.8",
          "kind": "patch",
          "published_at": "2026-04-01T20:26:25Z"
        },
        {
          "tag": "v0.6.7",
          "kind": "patch",
          "published_at": "2026-04-01T08:47:17Z"
        },
        {
          "tag": "v0.6.6",
          "kind": "patch",
          "published_at": "2026-04-01T08:30:56Z"
        },
        {
          "tag": "v0.6.5",
          "kind": "patch",
          "published_at": "2026-04-01T06:14:34Z"
        },
        {
          "tag": "v0.6.4",
          "kind": "patch",
          "published_at": "2026-04-01T06:03:41Z"
        },
        {
          "tag": "v0.6.3",
          "kind": "patch",
          "published_at": "2026-04-01T04:33:13Z"
        },
        {
          "tag": "v0.6.2",
          "kind": "patch",
          "published_at": "2026-04-01T03:52:27Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2026-04-01T03:14:35Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-04-01T01:24:11Z"
        },
        {
          "tag": "v0.5.24",
          "kind": "patch",
          "published_at": "2026-03-31T20:19:25Z"
        },
        {
          "tag": "v0.5.23",
          "kind": "patch",
          "published_at": "2026-03-31T19:54:50Z"
        },
        {
          "tag": "v0.5.22",
          "kind": "patch",
          "published_at": "2026-03-31T18:08:52Z"
        },
        {
          "tag": "v0.5.21",
          "kind": "patch",
          "published_at": "2026-03-31T17:22:43Z"
        },
        {
          "tag": "v0.5.20",
          "kind": "patch",
          "published_at": "2026-03-30T13:38:08Z"
        },
        {
          "tag": "v0.5.19",
          "kind": "patch",
          "published_at": "2026-03-30T04:52:20Z"
        },
        {
          "tag": "v0.5.18",
          "kind": "patch",
          "published_at": "2026-03-29T05:23:25Z"
        },
        {
          "tag": "v0.5.17",
          "kind": "patch",
          "published_at": "2026-03-29T05:04:36Z"
        },
        {
          "tag": "v0.5.16",
          "kind": "patch",
          "published_at": "2026-03-29T01:19:39Z"
        },
        {
          "tag": "v0.5.15",
          "kind": "patch",
          "published_at": "2026-03-28T16:01:42Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "719844be4d1f661bc493e1f205d12bc4e5890d38",
          "body": "feat(router): Physical Binning — Range Sieve (SSoT v2)",
          "is_bot": false,
          "headline": "Merge pull request #174 from LegionIO/feat/ssot-v2-physical-binning",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-07-23T23:03:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "95aded832fec7bcfb7876af6a89edc16887fda85",
          "body": "…full registry\n\nrouting_estimate_tool_defs was calling Settings::Extensions.filter_tools\nwhich returns the full registry (growing over daemon lifetime as extensions\nregister dynamically). The estimate diverged from what native_tool_definitions\nactually dispatches — tools=6105 estimate vs 8 tools on \n[…]\n_tools from\nnative_tools_requested_for_routing? — triggered tools WILL be injected\nso the lane must support :tools capability.\n\nRemoves temporary debug logging from range_sieve and estimate_breakdown.",
          "is_bot": false,
          "headline": "fix(routing): estimate_request_tokens must use discovered tools, not …",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-23T22:39:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e9f970aed813bab9ce9c1c080ef7bb46d32690c5",
          "body": "…ement\n\nServer-triggered tools (pattern matches on content like \"hello\" → Teams)\nare opportunistic — they should not exclude lanes without :tools capability.\nOnly client-requested tools and deferred tools gate on capability.\n\nThis was preventing V100 (no tools) from receiving small requests when\ntrigger_match happened to fire on the message content.",
          "is_bot": false,
          "headline": "fix(routing): triggered tools must not force :tools capability requir…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-23T21:03:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5b514e51155a2860fd992701a023ea3012877661",
          "body": "All sync API endpoints now return routing headers identifying which\nprovider, instance, and model handled the request. Enables e2e tests\nto assert Physical Binning routes to the correct instance without\nrelying on model name inference.\n\nHeaders: X-Legion-Provider, X-Legion-Instance, X-Legion-Model\nEndpoints: /v1/messages, /v1/responses, /v1/chat/completions, /api/llm/inference\nStreaming excluded (headers sent before routing is known).",
          "is_bot": false,
          "headline": "feat(api): emit X-Legion-Provider/Instance/Model response headers",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-23T20:45:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c4fd2b8c596f730fab0de997552900e6e9681e97",
          "body": "…(SSoT v2)\n\nAdds a 3-tier Range Sieve between hard filtering and weight selection:\n1. Specific match: lanes with declared range encompassing estimated_context\n2. Generalist: lanes with no range (intermediate failover)\n3. Full eligible: all hard-filter survivors (final fallback)\n\nInventory.write_lane\n[…]\ninstance settings — works for ALL providers without per-gem changes.\nBoundaries are lower-inclusive, upper-exclusive. Escalation via tried_lanes\ndrains each tier naturally before spilling to the next.",
          "is_bot": false,
          "headline": "feat(router): Physical Binning — Range Sieve steers by workload size …",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-22T22:23:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e6a954c4c11569277f8b938c6b39fec619456f62",
          "body": "…ext-compaction\n\nfix server tool result visibility for Claude and Codex streaming clients (v0.14.16)",
          "is_bot": false,
          "headline": "Merge pull request #172 from LegionIO/fix/content-block-leak-and-cont…",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-07-15T05:16:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7c5d2229add8882acc0fb919972c6908aa42ffe7",
          "body": "…sion-map)",
          "is_bot": false,
          "headline": "remove local Ruby pin (shared workflow handles 4.0→4.0.5 via ruby-ver…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-15T05:15:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a50481f0e1729392845894f9e6bc5dd8c52821b3",
          "body": "… settings)\"\n\nThis reverts commit fb8a662d2fa2bb476d2806d182ab4712c8476091.",
          "is_bot": false,
          "headline": "Revert \"revert Ruby pin: code fix handles 4.0.6 (escalation.rb + spec…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-15T05:08:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb8a662d2fa2bb476d2806d182ab4712c8476091",
          "body": null,
          "is_bot": false,
          "headline": "revert Ruby pin: code fix handles 4.0.6 (escalation.rb + spec settings)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-15T05:07:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7edc32588e7cef8a80b7a0cc0dfc19e85eb71d64",
          "body": "Ruby 4.0.6 Bug #22099 fix changes method dispatch behavior in a way that\nbreaks Concurrent::Hash bracket access through legion-settings. Pin to\n4.0.5 until the interaction is resolved upstream.",
          "is_bot": false,
          "headline": "pin Ruby 4.0.5 in CI matrix (4.0.6 has keyword-arg dispatch regression)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-15T04:57:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "20762b80da11051ee99571d139000756176de82b",
          "body": "… partial hashes\n\nRuby 4.0.6 (Bug #22099) fixed keyword-only methods silently accepting\npositional args. This exposed specs that replaced the entire routing hash\nwith partial config (losing :escalation sub-key), causing nil dereferences\nin pipeline_escalation_enabled?. Fix: write individual keys instead of\nreplacing the hash; remove .dig + || {} from escalation.rb since the\ndefaults are guaranteed present via settings.rb.",
          "is_bot": false,
          "headline": "fix Ruby 4.0.6 compat: stop overwriting Settings[:llm][:routing] with…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-15T04:52:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2ef46692048feaa9d8777165b7fa3ae9219eb270",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into fix/content-block-leak-and-context-compaction",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-07-15T04:19:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8c418f83f1d3d278de1195165e3df70903158f2f",
          "body": "…nts (v0.14.16)\n\nAnthropic Messages emitter sent server_tool_result content in a delta type\nthe SDK ignores; Responses emitter discarded results entirely. Both now\nsurface the result in a format clients parse. Also strips empty assistant\nmessages left behind after thinking extraction.",
          "is_bot": false,
          "headline": "fix server tool result visibility for Claude and Codex streaming clie…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-15T03:59:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7aa3350bb60f7e51dd68e6e6bba30a9156135424",
          "body": "…ext-compaction\n\nFix routing token under-count, history double-send, and router/dispatch parity (v0.14.11)",
          "is_bot": false,
          "headline": "Merge pull request #167 from LegionIO/fix/content-block-leak-and-cont…",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-07-09T08:21:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f1a26f05f709e8106baec5ddcdfb20dce67a9b83",
          "body": "…4.15)\n\nSame logical request must parse to an identical Canonical::Request regardless\nof client dialect. Three divergences broke that:\n\n1. upstream_body leaked into Canonical::Request.metadata. It was written at\n   parse, stripped before dispatch, and never read (native call_responses gets\n   the ra\n[…]\nhing the Anthropic single-message shape.\n\nNew offline specs (canonical_equivalence_spec, canonical_no_upstream_body_spec)\nmirror the legionio-e2e canonical-equivalence checks as the in-process oracle.",
          "is_bot": false,
          "headline": "Fix OpenAI Responses canonical divergences from Anthropic (SSOT, v0.1…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-09T06:03:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ae55b0c3baffce5c8028813f1c92dbdc8d6a3408",
          "body": "CI's Constant Safety check flags bare 'JSON.' even inside comments (it\nresolves to Legion::JSON under module Legion). Two prose comments mentioned\n'JSON.parse' as shorthand for a parse-as-object approach; reword to drop the\nbare constant. No code change.",
          "is_bot": false,
          "headline": "Reword comments to avoid bare JSON. token (CI const-bare-json)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-09T01:13:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cf66d83a8758f71f5bf4b27eb05a7405cc657afd",
          "body": "The context curator curated tool and assistant roles but passed every\nsystem-role message through unchanged. Claude Code's harness injections\n(task-tool nags repeated 18x, linter file-dumps) therefore accumulated\nunbounded in mid-conversation system messages, consuming up to ~25% of a\n60-80K dispatc\n[…]\nth\nrubocop:disable Style/ArrayIntersect — the cop's autocorrect rewrites\narray.any? { |x| str.include?(x) } to array.intersect?(str), which raises\nTypeError on a String arg (a latent rubocop -A trap).",
          "is_bot": false,
          "headline": "Strip client-harness noise from curator system role (GH#168, v0.14.14)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-09T01:08:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f285b5750a5a553538a329571503c99441dd960e",
          "body": "Some models (gemma via vLLM; ledger rows 337049/337111/337145/337174) emit\ntool-call intent as a raw literal token in content instead of the structured\ntool_calls field:\n\n  <|tool_call>call:NAME{key:<|\"|>value<|\"|>,...}<tool_call|>\n\nWithout synthesis the token reached the client verbatim — a \"tool c\n[…]\nctured call.\n\nCoverage: unit specs use captured-verbatim ledger strings; new matrix\nscenario (tool_leaked_token) asserts all three client formats synthesize the\ncall and never surface the raw markers.",
          "is_bot": false,
          "headline": "Synthesize leaked chat-template tool-call tokens (pattern 4, v0.14.13)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-09T00:33:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1910943e452b5f5dd79dd9edfe92ad6755fb8b64",
          "body": "GitHub Copilot validates model availability via GET /v1/models/:id before\nsending inference requests. The daemon returned 404 for models not in\nInventory (e.g. copilot-utility-small), even though it auto-routes them\nsuccessfully. Now returns a synthetic model object for models listed in\nthe new llm.routing.model_passthrough_ids setting.",
          "is_bot": false,
          "headline": "Fix BYOK model discovery for passthrough models (v0.14.12)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-09T00:21:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cb9cd3d175cd6acd6038f4b31c59f9f2ef4cae8e",
          "body": "…ch parity (v0.14.11)\n\nRouting must estimate the same payload dispatch actually sends. Four defects,\none oracle (ContextAccounting):\n\n1. estimate_request_tokens used a naive m[:content].to_s shadow estimator that\n   read structured content (Claude Code's shape) as near-zero, and counted only\n   @req\n[…]\ning.context_headroom (0.90) keeps the router context-window\n   filter in agreement with RouteAttempts#enforce_final_context_budget!.\n\ntoken_budget step now shares the same ContextAccounting estimator.",
          "is_bot": false,
          "headline": "Fix routing token under-count, history double-send, and router/dispat…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-03T20:01:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d6060cbbd74f8237d7290bd9c62afea33b1d9190",
          "body": "README: document the knowledge loop (curation -> Apollo -> RAG)",
          "is_bot": false,
          "headline": "Merge pull request #165 from LegionIO/credibility/knowledge-loop-readme",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-07-02T04:24:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f6b1bf9749771160505df30a1ce54715be2a94f0",
          "body": null,
          "is_bot": false,
          "headline": "Fix Apollo constants: distinguish local and shared stores",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-02T04:18:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c1c3ba239b8d327c895539850cf097f900bf340f",
          "body": null,
          "is_bot": false,
          "headline": "Fix Apollo constants: distinguish local and shared stores",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-02T04:07:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "313cd9c410ecf143b86fe5fa2503ab796f7c887b",
          "body": "Archival-not-truncation via drop_and_archive, the pipeline steps that\nclose the loop (knowledge_capture, rag_context, gaia_advisory), and\nApollo's confidence lifecycle with exact constants. Pipeline pulls,\nGAIA advises — worded to match the code, not the metaphor.",
          "is_bot": false,
          "headline": "README: document the knowledge loop (curation -> Apollo -> RAG)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-02T03:54:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "976a7577e28c7a15dff5b95936887d3a938fe852",
          "body": "Add curation production metrics doc; sharpen gemspec description",
          "is_bot": false,
          "headline": "Merge pull request #164 from LegionIO/credibility/curation-metrics-doc",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-07-02T03:02:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2f952331d132934560657eab4a931b2360edb290",
          "body": "Publishes the production ledger aggregates behind the curation claims\n(-0.1% single-turn through 97.7% at 50+ turns vs naive resend), with\nexplicit baseline definition, stock-vs-flow explanation, and caveats\nincluding the buckets where curation saves nothing. Gemspec now\ndescribes the gateway (tiered routing, mid-stream failover, curation)\ninstead of a generic routing blurb.",
          "is_bot": false,
          "headline": "Add curation production metrics doc; sharpen gemspec description",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-07-02T02:50:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "edbeb27639b78d25ca6bf812a21fe912d10d4d5f",
          "body": "…ext-compaction\n\nfix: Prompt.dispatch stops pre-baking settings defaults when Inventor…",
          "is_bot": false,
          "headline": "Merge pull request #163 from LegionIO/fix/content-block-leak-and-cont…",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-26T07:38:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1102405b8c9f4a57642f5dda0a1c54b3c73ab5ac",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into fix/content-block-leak-and-context-compaction",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-26T07:32:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c1fdf5453264a097fb65a1e452311d36b7800390",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump to 0.14.10, rubocop correction",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T07:29:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4c4c821e7e6424f6b266a1f84f2f3ca8fa45d60f",
          "body": "…e-baking\n\n- routing_resolution_for now passes chain_required_capabilities to\n  request_lane — requests with tools filter out lanes without :tools\n  capability (e.g. v100 with enable_tools=false).\n\n- Prompt.dispatch only falls back to settings defaults when Inventory\n  is empty (cold boot). When lan\n[…]\nel\n  so the Executor routes via request_lane by weight + context + caps.\n\n- Prompt.request nil guard relaxed: allows nil provider/model when\n  Inventory has lanes (Executor resolves via step_routing).",
          "is_bot": false,
          "headline": "fix: wire capabilities into routing + stop Prompt.dispatch default pr…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T05:41:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "41707a76ac54ee2d720056ce701b4f0c8e90f313",
          "body": "…y has lanes\n\nWhen Inventory is populated, Prompt.dispatch no longer fills in\ndefault_provider/default_model — lets the Executor's step_routing pick\nvia request_lane with full context (weight, context_window, tools).\n\nFixes: requests >16K context from GAIA/lex-agentic getting locked to\nv100 via model filter and failing with ContextOverflow instead of\nrouting to h200.\n\nCold boot (empty Inventory) still falls through to settings defaults.",
          "is_bot": false,
          "headline": "fix: Prompt.dispatch stops pre-baking settings defaults when Inventor…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T05:28:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eed4bcfaf707a7adb5dc5d71587628f89986ba41",
          "body": "…ext-compaction\n\nfix: routing estimate includes full payload (system + tools + thinking)",
          "is_bot": false,
          "headline": "Merge pull request #162 from LegionIO/fix/content-block-leak-and-cont…",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-26T04:30:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4d2f38230f1eac632640d6ea395d9024bcb1c1c4",
          "body": "resolve_routing_state normalizes provider to symbol via request_lane.",
          "is_bot": false,
          "headline": "test: fix prompt_spec string→symbol assertion for provider",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T04:27:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b068a096f535582d8277435dd5d2e841f96d3360",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into fix/content-block-leak-and-context-compaction",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-26T04:25:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cb6c2b3553f88f356aa88f56c1f0f6bed0ce30a6",
          "body": "estimate_request_tokens now accounts for all payload components —\nmessages, system prompt, tool definitions, and thinking config — matching\nwhat enforce_final_context_budget! checks at dispatch time.\n\nPreviously only messages were counted, causing requests with large tool\nschemas (e.g. Copilot Chat \n[…]\n.\n\nAlso removes the explicit_route/auto_route/intent_route gate from\nresolve_routing_state — request_lane is always consulted when Inventory\nhas lanes, enabling weight-based selection for all callers.",
          "is_bot": false,
          "headline": "fix: routing estimate includes system prompt, tools, and thinking",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T04:24:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "30d68dc1d8b99901f0e8a15b09cd0a10865c0b7e",
          "body": "…ext-compaction\n\nfix: ContentBlock inspect leak, context compaction, non-pipeline metering",
          "is_bot": false,
          "headline": "Merge pull request #161 from LegionIO/fix/content-block-leak-and-cont…",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-26T01:36:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5a357106db7b9708ab35bc3bc1f45d2b683d39be",
          "body": null,
          "is_bot": false,
          "headline": "style: rubocop -A spacing correction",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T01:33:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a88a423ce17c47aed4841a683479e760804f003b",
          "body": "The corrupted ContentBlock matrix spec requires the NoMethodError rescue\nin ContentBlock.from_hash shipped in lex-llm 0.6.3.",
          "is_bot": false,
          "headline": "chore: require lex-llm >= 0.6.3 (ContentBlock defensive guards)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T01:31:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cb80cbf34fa8f0d7cb527e6178361984a0401706",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into fix/content-block-leak-and-context-compaction",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-26T01:27:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "16be675f3330ac8949b8aab5f96551e378b69edf",
          "body": "format_response unconditionally emitted a message item with empty\noutput_text alongside function_call items. Codex interprets empty\noutput_text as \"no visible output\" and injects a complaint message\non every tool turn, degrading the conversation.\n\nThe streaming path (on_done) already guarded with `i\n[…]\nthe message item when content is\nempty and tool calls are present.\n\nReproduced: legionio-e2e spec/codex/vllm/tool_call_inspect_leak_spec.rb\nCell: Codex /v1/responses → LegionIO → vLLM (conv_id 147526)",
          "is_bot": false,
          "headline": "fix: suppress empty output_text message on tool_use responses",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T01:25:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3178b245658ce002570c00463484e770f8d0faf2",
          "body": "emit_non_pipeline_metering now reads tokens from response.usage\n(Canonical::Usage struct) instead of non-existent top-level accessors.\nFixes zero-token metering for lex-apollo, legion-gaia, lex-knowledge.\n\nAlso passes messages and response_content to metering events so ledger\ncaptures request_json on first write.\n\nBumps v0.14.7.",
          "is_bot": false,
          "headline": "fix: non-pipeline metering reads Canonical::Response correctly",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T00:49:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dc5604369c847651119ad4ec18614140dbe0f578",
          "body": "…loop\n\nTwo bugs fixed:\n\n1. ContentBlock inspect leak (Codex → vLLM, conv_id 147191):\n   step_context_store stored typed_msg.content (raw Array) instead of\n   typed_msg.text (extracted String). Serialization produced #inspect\n   strings that crashed on replay with NoMethodError (transform_keys).\n\n   \n[…]\n\n   payloads where one pass still exceeds the threshold by 2x.\n\n   Fix: loop halving until messages fit the target token budget.\n\nCells: Codex→vLLM (content_block_leak), Claude→vLLM (context_overflow)",
          "is_bot": false,
          "headline": "fix: ContentBlock inspect leak in context_store + context compaction …",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-26T00:48:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "28ab097270e84609bdaa93f62f31bd8a8a0ab666",
          "body": "fix: route rewrite for Kai /api/llm/inference/v1/* paths",
          "is_bot": false,
          "headline": "Merge pull request #159 from LegionIO/large-yolo-refactor",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-24T18:52:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e1b20a2a7347f5a884240f8189c321698d242758",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into large-yolo-refactor",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-24T18:51:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0b3b7ac3453a1e9bc5f332ef7fe7a35144dca86a",
          "body": "Kai sends requests to /api/llm/inference/v1/chat/completions but the\nOpenAI-compat handler lives at /v1/chat/completions. Added a before\nfilter to transparently rewrite the prefixed path.",
          "is_bot": false,
          "headline": "fix: route rewrite for /api/llm/inference/v1/* → /v1/* (Kai compat)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-24T03:56:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "935d66dff9cf5637f74f7dbdf3591e4e1e2581b1",
          "body": "fix: tool-aware context window enforcement + context overflow escalation (v0.14.3)",
          "is_bot": false,
          "headline": "Merge pull request #158 from LegionIO/large-yolo-refactor",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-23T08:51:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "258b0f19e440fb7a03059aee82f35e9b43806671",
          "body": "…rs=2k\n\nDispatch truncates at 5k (with model instruction to make smaller requests).\nCurator distills at 2k (aggressive context reduction for conversation history).",
          "is_bot": false,
          "headline": "tune: tool_result_max_dispatch_chars=5k, curation tool_result_max_cha…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-23T03:32:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2b155743b7ea8c6ddaeea83f95067401dfbf076a",
          "body": "…uncated",
          "is_bot": false,
          "headline": "fix: instruct model to make smaller requests when tool results are tr…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-23T03:29:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6b52f5639dba800560143cd4941809c0e5f787be",
          "body": "…eweight tiers\n\n- Embeddings: dispatch each chunk individually instead of sending array\n  to provider (fixes intermittent ContextOverflow on ollama RAG queries)\n- Reduce tool_result_max_dispatch_chars from 10k to 2k (trims oversized\n  tool results before provider dispatch)\n- Reweight tier defaults: direct=105, local=110, fleet=110, cloud=120,\n  frontier=150 (prefer higher-capability tiers when available)",
          "is_bot": false,
          "headline": "fix: per-chunk embed dispatch, trim tool_result_max_dispatch to 2k, r…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-23T03:23:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b24687b912097546cb0d7626ef2c548c4dfae2ed",
          "body": null,
          "is_bot": false,
          "headline": "refactor: move context_window_threshold to settings (0.90 default)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-23T02:23:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99c5754c310dd5b6a340d6675f31563d2fce74de",
          "body": null,
          "is_bot": false,
          "headline": "fix: add handle_exception to api_context_stats rescue block",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-23T02:10:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2f894bf0f68ed5756ebcee18f38f5d0d4938f8e4",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into large-yolo-refactor",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-23T02:08:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "406cf2493f0923f21192d6c7b81d20d9d16f8b62",
          "body": "…ion (v0.14.3)\n\nContext window enforcement now subtracts tool definition token budget before\ndeciding whether message compaction is needed. Context overflow is no longer\nunconditionally terminal — retries on a larger context lane when available.\nAlso enables X-Legion-Format: canonical by default and adds context_tokens_saved\nto the completion log.\n\nCloses #157",
          "is_bot": false,
          "headline": "fix: tool-aware context window enforcement + context overflow escalat…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-23T02:05:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c1116f38babd83a46ff20bfbfec9bcbbd0d6553f",
          "body": null,
          "is_bot": false,
          "headline": "Merge pull request #153 from LegionIO/large-yolo-refactor",
          "author_name": "Matthew Iverson",
          "author_login": "Esity",
          "committed_at": "2026-06-21T01:32:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "860b852f14ed6247d548744a5f8caced66ac81fb",
          "body": null,
          "is_bot": false,
          "headline": "chore: avoid constant safety false positive",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-21T01:18:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "775da2fa5782a7585b39a8fb11b1d9f9e0be607c",
          "body": null,
          "is_bot": false,
          "headline": "fix: tighten auto routing body model handling",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T22:25:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "715ad44ee2b51d4dd0dc269a2c2d606e3fc0872e",
          "body": null,
          "is_bot": false,
          "headline": "chore: quiet inventory policy logging",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T20:13:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9c5333827ba5272966e2afa262abf75f0cc35be1",
          "body": null,
          "is_bot": false,
          "headline": "chore: downgrade inventory write logs to debug",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T20:01:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4467e7b199ca1a5abc0f9a7c92b86b3558c3b39b",
          "body": null,
          "is_bot": false,
          "headline": "fix: preserve canonical request params through routing",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T17:20:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "64d5e95d89648a30c6ef785d13b975f05f6ef5fc",
          "body": "…ints (P4)\n\nThe N×N law (CLAUDE.md §N×N) requires the executor/router to be completely\nblind to provider API endpoint formats. Every request must flow through ONE\ncanonical path: parse→canonical→dispatch→canonical→render.\n\nThis commit removes all places where the executor knew about 'Responses API'\n\n[…]\n  lex-llm-* calls what endpoint'\n  'Each provider's wire-format translation lives entirely inside its\n   lex-llm-* gem — nothing in the router, executor, or routes ever\n   branches on a provider name'",
          "is_bot": false,
          "headline": "Fix 7 N×N violations: remove executor knowledge of provider API endpo…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T03:15:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b56fe439187dc155739219261ef89540c68dea4c",
          "body": "Settings shape :llm, :embedding is a hash { provider:, instance:,\ndefault_model: } — not a flat string. Original code read the whole hash\nand nil-checked, raising 'no embedding configured' even when the operator\nHAD configured embeddings.\n\nCall::Embeddings.generate now reads :default_model and pins \n[…]\nngs.rb so bracket access works (default_model: nil → ConfigError\nwith clear key path).\n\nSuite: 3079/0. Surfaces ship-blocker found during P6 e2e (apollo embed\ncalls were 4xx-ing despite valid config).",
          "is_bot": false,
          "headline": "Fix Call::Embeddings: read :default_model from hash settings shape",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T02:09:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3ab66328ad759574a6d552ac671991e5d1bf74af",
          "body": "All 9 lex-llm-* discovery_refresh actors call adapter.discover_offerings\n(via respond_to? check). Call::LexLLMAdapter only exposed #offerings, not\n#discover_offerings, so respond_to? returned false → lanes_from_instance\nsilently returned [] for every instance → Inventory stayed empty post-boot\n→ Rou\n[…]\nded to forward.\n\nRegression spec asserts adapter.respond_to?(:discover_offerings) and that\nthe call returns provider results.\n\nSuite: 3079/0. Surfaces empty-Inventory ship-blocker found during P6 e2e.",
          "is_bot": false,
          "headline": "Fix LexLLMAdapter#discover_offerings — empty Inventory regression",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T02:09:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "77221ec24ba93211eecc5ec0ae4cc3a03edce6c1",
          "body": "Data.define structs return inspect output from #to_s — counting that as\ntext produces ~3.4MB of inspect dump for a hello_ping payload, divided\nby 4 chars-per-token = 854K \"tokens\". Router.request_lane's\ncontext-window filter then rejected every lane (max ~200K window) and\nevery request returned NoLa\n[…]\ntes the accessor.\n\nRegression spec asserts hello-world Canonical::Message → <50 tokens,\nmulti-block sums correctly, legacy Hash messages still work, and a\ntool_calls-only assistant message → 0 tokens.",
          "is_bot": false,
          "headline": "Fix estimate_request_tokens: use Canonical::Message#text not Data#to_s",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T01:42:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fb353ef81fdc83497791357d2c30999473ecd257",
          "body": "legion-llm 0.14.0 requires lex-llm 0.6.0 (ScopedRefresher mixin writes to Inventory.write_lane;\nlegion-llm 0.14.0 is the first version that exposes that API). The >= 0.6.0 pin enforces the\ndependency. All 9 lex-llm-* gems also pin >= 0.6.0 in their gemspecs (separate repos, not\ncommitted here).\n\nRelease train publish order: lex-llm 0.6.0 → 9 lex-llm-* → legion-llm 0.14.0. Human-triggered.\n3070 examples, 0 failures. 0 rubocop offenses.",
          "is_bot": false,
          "headline": "P6 D-stage: pin lex-llm >= 0.6.0 in gemspec (release coordination)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T01:10:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03ed6b7cb7ccf158cd5e4a0ea16e86c09b126b3d",
          "body": "…n updates\n\nVersion bumped 0.13.3 → 0.14.0.\n\nCHANGELOG: full 0.14.0 entry — BREAKING (Inventory live store, request_lane, dual errors,\nembedding strict-pin, while loop), ADDED (write_lane API, Sweeper, RANKING v2, cooldown\ncircuit, PayloadBuilder, StreamAssembler trailers, fleet tier, admin endpoint\n[…]\nrsion 0.13.0→0.14.0; file-tree updated (request_lane replaces resolve/resolve_chain);\nrouting rules section rewritten for RANKING v2, Inventory live-map, fleet as first-class tier,\ndual error classes.",
          "is_bot": false,
          "headline": "P6 C2-C4: bump to v0.14.0; CHANGELOG; README/CLAUDE.md routing sectio…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T01:07:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0a1d0cf4e44a5cc4f85e16a1785f0526a715753a",
          "body": "…/; update require paths\n\nThe three compat-shim forwarder files created in P1 C2/C3 are now deleted:\n  lib/legion/llm/discovery.rb (→ inventory/discovery.rb)\n  lib/legion/llm/capabilities.rb (→ inventory/capabilities.rb)\n  lib/legion/llm/discovery/memory_gate.rb and system.rb (→ inventory/discovery/\n[…]\nth planning-error explanation (P0/C5 relocated only\ninject_anthropic_cache_control!; the registry bootstrap code is live infrastructure, not dead code).\n\n3070 examples, 0 failures. 0 rubocop offenses.",
          "is_bot": false,
          "headline": "P6 E-gate: delete compat shims discovery.rb/capabilities.rb/discovery…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T00:58:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "806789ab47cde8e5ab7fef78fc506b6c575c3f8e",
          "body": "…kip block\n\n- spec/legion/llm/inference/executor_attempts_loop_spec.rb tested the original\n  attempts.times loop shape; superseded by while-remaining.positive? per G26 (covered\n  in executor_spec.rb). Pure dead spec.\n- executor_spec.rb's 'EscalationChain deleted' skip block asserts on a class deleted\n  in P5 commit 6.\n\nSuite: 3075/0/5 pending -> 3070/0/0 pending. No code change.",
          "is_bot": false,
          "headline": "Delete P5 housekeeping: stale attempts.times spec + EscalationChain s…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-20T00:37:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dfaf0c6502f7cecf3b3dd169c33b2fd20459c807",
          "body": null,
          "is_bot": false,
          "headline": "P5 results doc — commit map, deviations, confirmations for P6",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T21:01:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "30a1264e5e59149b5a3394a198f7372e110f337c",
          "body": "Removes the @escalation_chain iteration machinery (the old loop body) now\nthat run_provider_call_with_attempts (the while remaining.positive? loop)\nis the only dispatch path.\n\nDeleted from executor/escalation.rb:\n- run_provider_call_with_escalation (old loop body)\n- run_escalation_resolution, attemp\n[…]\nult_escalation_chain/skip_same_tier!/\nskip_all_provider_model_instances!/@escalation_chain → 0 non-live callers in lib/.\nMatrix harness: 47 examples, 0 failures. Full suite: 3075 examples, 0 failures.",
          "is_bot": false,
          "headline": "P5 C6: Delete old executor escalation scaffolding; zero non-test callers",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T20:59:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7ead115bc903ad32b8aa564d71b9a208ec16ae11",
          "body": "RANKING v2 replaces auto-rules with operator-set lane weights. The 9\nlex-llm-* gems' discovery_refresh actors call this method defensively\n(respond_to? guarded), so the stub keeps them working through v0.14.0\nwhile their call sites are removed in N+1.\n\nRefs: #155 (delete in v0.15.0; blocked-by #154)\n      #154 (checklist for the 9 lex-llm-* gems)",
          "is_bot": false,
          "headline": "Add Router.populate_auto_rules no-op deprecation stub",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T20:43:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "74a7967a77b4fa489b907484b8a1582ca526cfbc",
          "body": "… model pin\n\nG15: Call::Embeddings.generate / generate_batch now route through\nRouter.request_lane(type: :embedding, models: [pinned_model]) per the\nInventory SSOT design. Strict model pin — no cross-model failover so\nvector-comparability is preserved. A down pinned lane → NoLaneAvailable\n(400), not\n[…]\nesolve_provider tests\nremoved (dead code now deleted).\n\nG15 invariant: alternate embedding model in Inventory is never used when\npinned model lane is healthy; pinned model lane down → NoLaneAvailable.",
          "is_bot": false,
          "headline": "P5 C4: Embedding pipeline rewires through Router.request_lane; strict…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T20:40:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a43cf4badfdfbb9f84953dbbe067a187f0dcafeb",
          "body": "…no SSE event\n\nStreamAssembler now requires initial_lane: (non-nil; nil raises ArgumentError)\nso the assembler always has a lane on hand (H-I / sonnet G6 / D-K).\n\nAdd provider_failover_pending!(from:): clears canonical buffer (full_text,\nfull_thinking, open tool calls, thinking blocks), appends :fai\n[…]\nempts already calls begin_dispatch_on\non each iteration.\n\nP0/B8 silent_failover_spec turns green: no :'provider-switch' SSE event;\ndebug trailers present; assembler construction requires non-nil lane.",
          "is_bot": false,
          "headline": "P5 C3: StreamAssembler mid-stream failover contract; debug trailers; …",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T20:24:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6cbc67ac5cedcc597df5464f1b687b7e91c9f708",
          "body": "Add lib/legion/llm/inference/executor/payload_builder.rb — single ingress site\nfor routing_payload construction from headers, body, and classification.\n\nPayloadBuilder.parse_and_validate_header validates x-legion-tiers (and future\ntaxonomy headers) against Legion::Extensions::Llm::Taxonomies::TIERS \n[…]\nngs: routing.allow_body_routing_hints: false added to defaults.\n\nP0/B8 header_validation_spec turns green. Spec migrated to use real Sinatra app\nwith Legion::LLM.started forced true for route testing.",
          "is_bot": false,
          "headline": "P5 C2: PayloadBuilder single ingress site; x-legion-* header validation",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T20:15:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5c8e75bc7f043fbd99321b4b83e0ce7b0a9998b8",
          "body": "…r translator\n\nReplace executor's chain-based escalation loop with the bounded\nwhile remaining.positive? stateless loop (G26/D-C). Dual-error semantics:\nNoLaneAvailable on attempt_idx==0 nil (HTTP 400), EscalationExhausted on\nremaining exhaustion or mid-loop nil with attempt_idx>=1 (HTTP 503+Retry-A\n[…]\nl_responses, claude_code conformance — updated to use Inventory lanes so\nRouter.request_lane finds providers in the new loop.\n\nP0/B3 + P0/B8 RED specs (no_loop_do, internal_error_terminal) turn green.",
          "is_bot": false,
          "headline": "P5 C1: while remaining.positive? loop; dual-error semantics; API erro…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T20:00:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b64caed3e2cd902305bc59bb46fae150bdff29c6",
          "body": null,
          "is_bot": false,
          "headline": "P4 results doc — audit greps, deviations, confirmations for P5",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T19:01:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "771dc576c292ed75689c10ec5c8f438e437fcf26",
          "body": "Availability:\n  - Add lane_rejection_reason(lane:, **): reads lane[:health] directly,\n    returns :policy_denied / :circuit_open / :unavailable / nil.\n    This is the P4+ lane-based API. The old resolution-based rejection_reason\n    is kept until P5 rewrites the executor's EscalationChain loop.\n\nRul\n[…]\nc.rb: deleted with it.\n  - router.rb: remove require_relative 'router/rule'.\n\nrubocop --only Legion/Framework: 0 offenses across legion-llm.\nlex-llm-{anthropic,bedrock,openai,vllm,ollama}: 0 failures.",
          "is_bot": false,
          "headline": "P4 C5: Add lane_rejection_reason to Availability; delete Rule (P4)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T19:00:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8dcfce84516103e12e7907e6a73d10ab1a0f3bec",
          "body": "Fills spec/legion/llm/router/request_lane_spec.rb with 40 examples covering:\n  - Hard filters: type, tiers, providers, instances, models, capabilities,\n    thinking (:require/:forbid/:any), privacy: :strict, estimated_context\n  - Capability normalization: :tools ↔ :function_calling ↔ :tool_use (PR #\n[…]\ning.\nPreviously normalize([:tool_use]) produced [:tool_use, :tools] — the non-\ncanonical :tool_use was never in the lane's normalized set, causing false\nrejections for request :tool_use → lane :tools.",
          "is_bot": false,
          "headline": "P4 C4: Exhaustive request_lane specs + capability canonicalization fix",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T18:53:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ef360a8f332167d4c9dd7f66f4c8cfdee62afa4c",
          "body": "…th (P4 C3)\n\nReplaces:\n  - Router.resolve / resolve_chain with Router.request_lane\n  - Router::Candidates effective_priority scoring with lane_weight bucket+sample\n  - RuleGenerator auto-rule materialization with settings-driven lane_weight\n  - Arbitrage cost-table with Phase-2 cost_factor (deferred\n[…]\n file\n  - API routing endpoints: return empty rule list (rule engine deleted)\n  - startup_spec.rb: migrated to assert SettingsObserver.attach! and absence of\n    populate_auto_rules call per phase doc",
          "is_bot": false,
          "headline": "Delete the rule/chain selection machine — request_lane is the only pa…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T18:47:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "90aabd13d959e108d74cdd04697a9c55d45394de",
          "body": "…ve/resolve_chain callers (P4)\n\nSwitches the executor's routing_resolution_for from Router.resolve/resolve_chain\nto Router.request_lane, wrapping the returned lane Hash in a Resolution value\nobject for downstream compatibility.\n\nAlso migrates all other internal callers that would fail after commit 3\n[…]\n - prompt_spec: replace Router.resolve mocks with inventory fixtures\n\nAudit: zero non-test Router.resolve/resolve_chain callers in lib/ (excluding\nthe guarded structured_output.rb respond_to? branch).",
          "is_bot": false,
          "headline": "P4 C2: Wire executor + all callers to Router.request_lane; zero resol…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T18:25:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "400400d17293dae35bcb46f346044b7a5d09fa50",
          "body": "…hausted/InvalidHeader\n\nAdds the stateless Router.request_lane(**routing_payload) alongside existing\nRouter.resolve/resolve_chain. Pure function: hard filters → drop tried_lanes\nand lane_weight ≤ 0 → group_by(weight) → max bucket → .sample(rng).\n\nCapability normalization via Inventory::Capabilities.\n[…]\n:Errors::InvalidHeader (header:, got:, valid:)\n\n.rubocop.yml: CountKeywordArgs: false for Metrics/ParameterLists so the all-\nkwargs method signature is idiomatic; removes redundant disable directives.",
          "is_bot": false,
          "headline": "P4 C1: Add Router.request_lane + Errors::NoLaneAvailable/EscalationEx…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T18:02:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4999a894826b78262dcc5f37a9420f418b073d5d",
          "body": null,
          "is_bot": false,
          "headline": "P3 results doc — audit greps, deviations, HEAD SHA for P4",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T17:50:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3eeb965eeda4df885c5a5601f9bc70795ade0dc3",
          "body": "C3 — spec/legion/llm/inventory/compliance_spec.rb (replaces P0 placeholder):\n  - blacklist rejects listed model; allows non-listed\n  - whitelist denies model not on list; allows listed\n  - whitelist precedence (sonnet B5): blacklist IGNORED when whitelist set;\n    model on both lists is admitted (wh\n[…]\ncklisted model\n    (defense-in-depth: library callers that bypass Router cannot route\n    to a denied model by passing a hardcoded model name)\n  - Confirmed: non-blacklisted model passes without error",
          "is_bot": false,
          "headline": "P3 C3+C4: Comprehensive policy specs + dispatch defense-in-depth",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T17:49:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "91d2f57feefc01ac92e6cc7d48153a18c2bbfe2e",
          "body": "Removes the parallel discovery cache that had zero readers after P1+P2\ncollapsed Inventory to a single live store:\n\n  - inventory/discovery.rb: delete @discovered_models, @discovered_models_at,\n    discovered_models, cached_discovered_models, discovered_models_cache_schema_stale?,\n    refresh_discov\n[…]\nll was P1 C6b transition bridge.\n\n  Specs migrated: discovery_spec.rb, embeddings_spec.rb, executor_spec.rb,\n  availability_spec.rb, router_spec.rb, model_divergence_spec.rb,\n  rule_generator_spec.rb.",
          "is_bot": false,
          "headline": "Delete Legion::LLM::Discovery cache surface (P3 C2)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T17:44:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ba610baca66318be1490e286c6bdfe0ab6f96d02",
          "body": "After P1 made Inventory a live store and P2 routed health into it, the\nmulti-source compose-on-read machinery has zero callers. lex-llm-* gems\nwrite lanes directly via Inventory.write_lane; HealthTracker writes the\nhealth field; reads are filtered map lookups.\n\nRemoved from lib/legion/llm/inventory.\n[…]\nulti_instance_spec.rb.\n\nEliminates the policy-leak path: discovery side previously bypassed\nwhitelist/blacklist filtering. Compliance is now fail-closed at the single\nInventory.write_lane choke point.",
          "is_bot": false,
          "headline": "Delete parallel offerings paths — Inventory is the only catalog (P3 C1)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T17:30:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1dfdaddf2f734a961ba4e5c0b7e3e2d1748dd49d",
          "body": null,
          "is_bot": false,
          "headline": "P2 results doc — deviations, confirmations, HEAD SHA for P3",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T10:14:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5e3f3c394293408f823925d4a95786a04d6d1403",
          "body": "Remove circuit_state(provider, instance:, offering_id:) and\nworst_circuit_state(instances) — the last read-facing public methods\nthat polled HealthTracker at request time. All callers now read\nlane[:health] from Inventory directly.\n\n- health_tracker.rb: delete circuit_state / worst_circuit_state\n- i\n[…]\nvailability/escalation/executor specs seeded with Inventory lanes\n  so HealthTracker circuit writes flow through to circuit_open? checks\n\n3281 examples, 0 failures, 25 pending (all P3–P5 future work).",
          "is_bot": false,
          "headline": "P2 C4: Delete HealthTracker request-time read API",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T10:13:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5dd56b13600b7e3ccf589cc5af0d331972b25a49",
          "body": "Selection-time code no longer calls HealthTracker for circuit state or\nmodel-denied checks. Reads lane[:health] from Inventory instead. Falls\nback to HealthTracker for cold-boot / pre-ScopedRefresher state only.\n\n- availability.rb: rejection_reason reads Inventory lanes_for health\n  first; HealthTra\n[…]\nide\n\nGrep-CI gate:\n  grep -rn \"health_tracker\\.\" lib/legion/llm/router/ lib/legion/llm/inference/ \\\n    | grep -v health_tracker.rb | grep -v allowlist:write-side\n  → empty\n\n3284 examples, 0 failures.",
          "is_bot": false,
          "headline": "P2 C2: Availability reads lane[:health] only; grep-CI gate clear",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T09:37:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7f03c0326c35c55e6c7b6b9764c6dfeba9b1b904",
          "body": "HealthTracker now writes the derived health block to all matching\nInventory lanes on every state transition: closed→open, half_open→open,\nany→closed (success), and on deny_model (single-lane write only).\n\n- Extract do_transition_circuit!(key:, to_state:) called from all\n  transition sites (error han\n[…]\nacker_inventory_writes_spec.rb (7 new examples),\nhealth_preserve_spec.rb (G21 pending guard removed, now green),\nhealth_mult_spec.rb (G23 pending guard removed, now green).\n\n3284 examples, 0 failures.",
          "is_bot": false,
          "headline": "P2 C1: HealthTracker writes lane health on circuit transitions",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T09:31:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e7f032c070c9f2084ca6492c849f4ba96d6c606c",
          "body": null,
          "is_bot": false,
          "headline": "removing files",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T09:21:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ab7d0817b2c8e8e74ce58b67937555d206c248fb",
          "body": null,
          "is_bot": false,
          "headline": "P1 results doc — deviations, confirmations, HEAD SHA for P2",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T07:21:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b7a67f6d90b9d237b3376b55c44cafae91653cc7",
          "body": "compat.rb: Add method_missing/respond_to_missing?/instance_variable_set/get\ndelegation from Legion::LLM::Discovery (real module from rule_generator.rb)\nto Legion::LLM::Inventory::Discovery. Mirror nested constants (System,\nMemoryGate, DISCOVERED_MODELS_SCHEMA_VERSION etc.). Fixes 291 spec failures\nf\n[…]\ne constant path.\nFix lane_weight default (instance/model default to 100, not provider_weight).\nFix discovery_offerings to use Legion::LLM::Discovery (compat) so allow()\nmocks in specs are intercepted.",
          "is_bot": false,
          "headline": "P1 exit: Fix spec regressions from Discovery module move",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T07:19:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5b5d029edbe51cc09461de2ffe9be385be1fa3f1",
          "body": "…ing rule)",
          "is_bot": false,
          "headline": "P1 C10: Exception log-level audit — :debug → :warn minimum (D-J stand…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T06:51:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "235ff9f01092d1fdda89df09948044cd21d1a32c",
          "body": "…int (G28)\n\nInventory::SettingsObserver.attach! wired on Legion::LLM.start.\nhandle_change(path:) rewrites affected provider lanes with updated weights,\npreserving circuit health (G21). Clamps TTL >= 0 (D8/sonnet G7).\nrewrite_all_lanes! handles tier_weights changes.\n\nNOTE: Legion::Settings.observe() \n[…]\n Admin endpoint is the manual fallback.\n\nPOST /api/llm/inventory/refresh registered in api.rb and inventory_admin.rb.\nsettings_reweight_spec green (direct handle_change call — no observer API needed).",
          "is_bot": false,
          "headline": "P1 C9: SettingsObserver + POST /api/llm/inventory/refresh admin endpo…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T06:48:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5dc027051207e0c2536349aa82c736af465e8509",
          "body": "offerings() now reads from Concurrent::Map live store first (zero recompute\nwhen store is populated). Falls back to compose_offerings() when store is\nempty (test env, cold boot). compose_offerings stays for P3 when callers\nfully migrate. Per-call recompute eliminated for populated stores.\n\nlanes_for\n[…]\nes() removed — callers migrated to lanes_for() in commit 1.\n\nP0 instrumentation removed: emit_p0_capture, capture_summary, p0_exchange_id\nThread.current writes deleted from executor.rb and routing.rb.",
          "is_bot": false,
          "headline": "P1 C8: Switch offerings() to live map read; remove P0 instrumentation",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T06:44:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fb1ddace0a9f3b39a11e400a0df51affa5b68104",
          "body": "Sweeper class in lib/legion/llm/inventory/sweeper.rb iterates via\nInventory.expired_ids (never .send(:map) per M3) and calls delete_lane\nfor each expired entry. Static-catalog lanes (expires_at: nil) immune.\n\nself.sweep! class method enables direct invocation from specs.\nEvery actor interface (time/manual) wired for daemon registration.\nRequired from llm.rb. P0/B5 spec green (no Timecop dependency — stubs\nexpired_ids directly).",
          "is_bot": false,
          "headline": "P1 C7: Ship Inventory::Sweeper TTL safety net",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T06:36:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ea534f12037c52f40e3e1cf38db1af296d596fcf",
          "body": "…es/expired_ids)\n\nAdd Concurrent::Map live store with full write API:\n- write_lane: validates 5-part id (G22), policy filter, health: :preserve sentinel (G21),\n  compute_lane_weight with G23 magnitude-preserving -1.0 for denied/open, freeze-on-write (M10)\n- delete_lane: warn-logs on miss (standing r\n[…]\nive store first, falls back to offerings() during P1 transition.\n\nDrop P0/B1 skip guards. Lane id validation (B8 subset) green. Health tests needing\nHealthTracker→Inventory wiring moved to P2-pending.",
          "is_bot": false,
          "headline": "P1 C5: Introduce Inventory write API (write_lane/delete_lane/lane/lan…",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T06:21:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "02f936e15ca02aa9e40ebf5b42ce3b512c41b944",
          "body": "Module paths: Legion::LLM::Discovery::{System,MemoryGate} →\nLegion::LLM::Inventory::Discovery::{System,MemoryGate}.\nOld paths become require-forwarder shims.\nrouter.rb updated to require from new paths.\nrouter/candidates.rb updated to use fully-qualified Inventory::Discovery::MemoryGate.\ninventory/discovery.rb updated System refs to new qualified path.\ndiscovery/ directory now contains only forwarder shims (rule_generator.rb stays; deleted P4).",
          "is_bot": false,
          "headline": "P1 C4: Move discovery/{memory_gate,system}.rb → inventory/discovery/",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T06:15:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f385b8a302cb85be20468c594903925146f46f7d",
          "body": "Module path: Legion::LLM::Capabilities → Legion::LLM::Inventory::Capabilities.\nOld path is a require_relative forwarder. compat.rb const_missing alias added.\nrouter.rb and router/availability.rb updated to require new path.\nCapabilities calls in availability.rb use fully-qualified Legion::LLM::Inventory::Capabilities.",
          "is_bot": false,
          "headline": "P1 C3: Move capabilities.rb → inventory/capabilities.rb (move-only)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T06:09:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4e4f809c20068203f1487974befff634c3df482d",
          "body": "Module path: Legion::LLM::Discovery → Legion::LLM::Inventory::Discovery.\nOld path lib/legion/llm/discovery.rb becomes a require_relative forwarder.\ncompat.rb const_missing alias Discovery → Inventory::Discovery for cross-gem callers.\nIn-gem refs updated: inventory.rb now uses Legion::LLM::Inventory::Discovery.\nSystem.* calls use fully-qualified path until commit 4 moves system.rb.",
          "is_bot": false,
          "headline": "P1 C2: Move discovery.rb → inventory/discovery.rb (move-only)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T06:05:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6bb973b96c9bad40abe873fe0b0af4b7b909f999",
          "body": "Add Inventory.lanes_for(provider:, instance:, type:, model:, **) as a filtered\nread over offerings(). Migrate router.rb inventory_default_model off the old\nrouting_candidates method onto lanes_for(provider:, type: :inference).\n\nrouting_candidates stays for now; deleted in commit 8.\nUpdate determinism spec to stub lanes_for alongside routing_candidates.",
          "is_bot": false,
          "headline": "P1 C1: Migrate inventory_default_model to Inventory.lanes_for(**)",
          "author_name": "Esity",
          "author_login": "Esity",
          "committed_at": "2026-06-19T05:58:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 100,
      "commits_last_year": 1119,
      "latest_release_at": "2026-07-23T23:04:40Z",
      "latest_release_tag": "v0.14.17",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 19,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 4
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 100,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "legion-llm",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [],
          "ecosystem": "rubygems",
          "matches_repo": true,
          "registry_url": "https://rubygems.org/gems/legion-llm",
          "is_deprecated": false,
          "latest_version": "0.14.17",
          "repository_url": "https://github.com/LegionIO/legion-llm",
          "versions_count": 141,
          "total_downloads": 34511,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2026-03-16T18:03:55.592000Z",
          "latest_published_at": "2026-07-23T23:04:41.644000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 3,
      "stars": 2,
      "watchers": 1,
      "fork_history": {
        "days": [
          {
            "date": "2026-04-17",
            "count": 1
          },
          {
            "date": "2026-04-21",
            "count": 1
          },
          {
            "date": "2026-04-22",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 3,
        "total_forks": 3
      },
      "star_history": null,
      "open_issues_and_prs": 8
    },
    "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": [],
      "largest_source_bytes": 66627,
      "source_files_sampled": 495,
      "oversized_source_files": 2,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 7940
    },
    "dependencies": {
      "manifests": [
        "Gemfile"
      ],
      "advisories": {
        "error": "No resolved dependencies carried a version and a supported ecosystem",
        "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": 22,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "rubygems"
      ],
      "dependencies": [
        {
          "name": "legion-settings",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rack-test",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": "~> 2.0"
        },
        {
          "name": "rake",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rspec",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rspec_junit_formatter",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rubocop",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rubocop-legion",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rubocop-legion",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": ">= 0.1.8"
        },
        {
          "name": "simplecov",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "sinatra",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "webmock",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "legion-settings",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rack-test",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rake",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rspec",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rspec_junit_formatter",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rubocop",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rubocop-legion",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "simplecov",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "sinatra",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "webmock",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "concurrent-ruby",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "event_stream_parser",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "legion-cache",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "legion-json",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "legion-logging",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "legion-transport",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "lex-knowledge",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "lex-llm",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "pdf-reader",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "sinatra-contrib",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "tzinfo",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 22,
        "direct_count": 10,
        "indirect_count": 12
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 2,
        "merged_prs": 95,
        "open_issues": 6,
        "closed_ratio": 0.915,
        "closed_issues": 65,
        "closed_unmerged_prs": 5
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "Esity",
          "commits": 1068,
          "avatar_url": "https://avatars.githubusercontent.com/u/1851830?v=4"
        },
        {
          "type": "User",
          "login": "iamhollow",
          "commits": 8,
          "avatar_url": "https://avatars.githubusercontent.com/u/7559688?v=4"
        },
        {
          "type": "User",
          "login": "armstrongsamr",
          "commits": 8,
          "avatar_url": "https://avatars.githubusercontent.com/u/205221693?v=4"
        },
        {
          "type": "User",
          "login": "web-flow",
          "commits": 5,
          "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4"
        }
      ],
      "contributors_sampled": 4,
      "top_contributor_share": 0.981
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        ".rubocop.yml"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 3,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "6 out of 6 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/6 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 6,
            "reason": "project has 2 contributing companies or organizations -- score normalized to 6",
            "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": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 0 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": 10,
            "reason": "SAST tool is run on all commits",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "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": "719844be4d1f661bc493e1f205d12bc4e5890d38",
        "ran_at": "2026-07-23T23:12:20Z",
        "aggregate_score": 5.9,
        "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-23T23:04:47Z",
      "oldest_open_prs": [
        {
          "number": 152,
          "created_at": "2026-06-17T20:30:58Z",
          "last_comment_at": "2026-06-26T19:04:49Z",
          "last_comment_author": "madhakish"
        },
        {
          "number": 156,
          "created_at": "2026-06-21T19:54:32Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-23T23:03:48Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 154,
          "created_at": "2026-06-19T20:40:44Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 155,
          "created_at": "2026-06-19T20:41:07Z",
          "last_comment_at": "2026-06-19T20:41:17Z",
          "last_comment_author": "Esity"
        },
        {
          "number": 166,
          "created_at": "2026-07-03T16:41:04Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 169,
          "created_at": "2026-07-14T21:17:12Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 171,
          "created_at": "2026-07-14T23:22:47Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 173,
          "created_at": "2026-07-22T21:30:35Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/LegionIO/legion-llm",
    "host": "github.com",
    "name": "legion-llm",
    "owner": "LegionIO"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 68,
      "inputs": {
        "security": 59,
        "vitality": 82,
        "community": 48,
        "governance": 62,
        "engineering": 84
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 82,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 77,
            "inputs": {
              "commits_last_year": 1119,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 19
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "19/52 weeks with commits",
                "points": 13.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 19
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "1119 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1119
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 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": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 100,
              "latest_release_tag": "v0.14.17",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 4
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "100 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~4 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 4
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 48,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 2,
            "inputs": {
              "forks": 3,
              "stars": 2,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "2 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "3 forks",
                "points": 2.5,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "1 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "excellent",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 92,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": true,
              "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": "recognized license (Apache-2.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "Apache-2.0"
                    }
                  }
                ],
                "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": 13.5,
                "status": "met",
                "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
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 59,
            "inputs": {
              "packages": [
                "legion-llm"
              ],
              "dependents": null,
              "ecosystems": "rubygems",
              "total_downloads": 34511,
              "monthly_downloads": null
            },
            "components": [
              {
                "key": "total_downloads",
                "name": "Total downloads",
                "detail": "34,511 downloads all-time across rubygems",
                "points": 47.2,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_total",
                    "params": {
                      "count": 34511,
                      "ecosystems": "rubygems"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 62,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 21,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 4,
              "top_contributor_share": 0.981
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 98% of commits",
                "points": 0.4,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 98
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "4 contributors",
                "points": 5.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 79,
            "inputs": {
              "merged_prs": 95,
              "open_issues": 6,
              "closed_issues": 65,
              "issue_closed_ratio": 0.915,
              "closed_unmerged_prs": 5
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "92% of issues closed",
                "points": 42.8,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 92
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "95/100 decided PRs merged",
                "points": 36.3,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 95,
                      "decided": 100
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/6 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "followers": 23,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "LegionIO",
              "public_repos": 199,
              "account_age_days": 2778
            },
            "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": "23 followers of LegionIO",
                "points": 9.9,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 23,
                      "login": "LegionIO"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "199 public repos, account ~7 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 199
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 7
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "legion-llm"
              ],
              "ecosystems": "rubygems",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on rubygems",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "rubygems"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 0 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "141 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 141
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 84,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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": ".rubocop.yml",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".rubocop.yml"
                    }
                  }
                ],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "6 out of 6 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "topics": [
                "ai",
                "legion-core",
                "legionio",
                "llm",
                "ruby"
              ],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "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": 25,
                "status": "met",
                "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": "5 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 59,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 59,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 5.9
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "6 out of 6 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "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 0/6 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 1.5,
                "status": "partial",
                "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.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 0 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 run on all commits",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "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": 1
            },
            "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": "moderate",
        "name": "AI Readiness",
        "value": 58,
        "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.82,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 7940
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, 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": "82 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 82,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 38,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": ".rubocop.yml",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".rubocop.yml"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "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": "moderate",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "primary_language": "Ruby",
              "largest_source_bytes": 66627,
              "source_files_sampled": 495,
              "oversized_source_files": 2
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Ruby without a type-check config",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_typecheck_config_language",
                    "params": {
                      "language": "Ruby"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "2/495 source files over 60KB",
                "points": 54.8,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 495,
                      "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",
    "No resolved dependencies carried a version and a supported ecosystem"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-23T23:12:37.106627Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/l/LegionIO/legion-llm.svg",
  "full_name": "LegionIO/legion-llm",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

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

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

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