Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 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 estrellas⑂ 3 forksdesde mar 2026Ver en GitHub ↗

LegionIO/legion-llm tiene un índice de salud de 68 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Engineering Quality (84/100) y la más baja, Community & Adoption (48/100). Se actualizó por última vez hoy. Una sola persona concentra la mayor parte del trabajo reciente.

68
global / 100
Moderado

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala de 1 a 100. El resultado global parte de su media; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe el límite 49 (En riesgo). Preparación para IA queda fuera.

68
Excelente85-100Ejemplar; cumple prácticamente todos los criterios evaluados
Bueno70-84Saludable; carencias menores
Moderado50-69Aceptable con carencias notables; se recomienda revisión
En riesgo30-49Debilidades significativas; su adopción exige cautela
Crítico1-29Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

Cada eje es una categoría. La forma importa más que la media: un proyecto sano llena toda la figura, mientras que un perfil de picos y cráteres indica que la fortaleza en una dimensión enmascara el riesgo en otra.

Titularidad

LegionIOOrganización
23 seguidores199 repositorios públicosdesde dic 2018

Este repositorio está respaldado por una organización: una custodia compartida y responsable que puede sobrevivir a cualquier mantenedor individual.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
RubyGemslegion-llm0.14.17-141hace 0 días

Métricas por categoría

Vitalidad

¿Está vivo el proyecto: se escribe código y se publican versiones?

82Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
13.2/36Cadencia de commits — 19/52 semanas con commits
18/18Volumen de commits — 1119 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year1119
human_commit_share1
days_since_last_push0
active_weeks_last_year19
Cómo se puntúa
27/27Publica versiones — 100 versiones publicadas
36/36Recencia de las versiones — última versión hace 0 días
27/27Cadencia de publicación — una versión cada ~4 días
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Datos de entrada utilizados
releases_count100
latest_release_tagv0.14.17
releases_from_tagsno
days_since_latest_release0
mean_days_between_releases4

Comunidad y Adopción

¿Tiene el proyecto usuarios, descargas, atención y unas condiciones acogedoras para quienes contribuyen?

48En riesgo · 18% del índice global
Cómo se puntúa
0/60Estrellas — 2 estrellas
2.5/25Forks — 3 forks
0/15Observadores — 1 observadores
Datos de entrada utilizados
forks3
stars2
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (Apache-2.0)
18/18Guía CONTRIBUTING
13.5/13.5Código de conducta
0/7.2Plantilla de issues
6.3/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributing
has_issue_templateno
has_code_of_conduct
has_pull_request_template
Cómo se puntúa
47.2/80Descargas totales — 34.511 descargas históricas en rubygems
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packageslegion-llm
dependents
ecosystemsrubygems
total_downloads34.511
monthly_downloads
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

¿Sobrevivirá el proyecto a sus personas: factor bus, capacidad de respuesta, quién lo respalda y mantenimiento del paquete?

62Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0.4/22.5Distribución de commits — el principal contribuyente firma el 98% de los commits
5.4/13.5Amplitud de contribuyentes — 4 contribuyentes
6/10OpenSSF Scorecard: Contributors — project has 2 contributing companies or organizations -- score normalized to 6
Datos de entrada utilizados
bus_factor1
contributors_sampled4
top_contributor_share0,981
Cómo se puntúa
42.8/46.8Resolución de issues — 92% de issues cerradas
36.3/38.3Aceptación de PR — 95/100 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/6 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs95
open_issues6
closed_issues65
issue_closed_ratio0,915
closed_unmerged_prs5
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
9.9/25Alcance del propietario — 23 seguidores de LegionIO
25/25Trayectoria — 199 repos públicos, cuenta de ~7 años
Datos de entrada utilizados
followers23
owner_typeOrganization
is_verified
owner_loginLegionIO
public_repos199
account_age_days2778
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en rubygems
35/35Recencia de publicación — última publicación hace 0 días
20/20Historial de versiones — 141 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packageslegion-llm
ecosystemsrubygems
any_deprecatedno
min_days_since_publish0

Calidad de Ingeniería

¿Existen unas prácticas mínimas de ingeniería y documentación?

84Bueno · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 1 flujo(s) de trabajo
24/24Pruebas presentes
16/16Configuración de linter — .rubocop.yml
0/9.6Hooks de pre-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
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_config
has_precommit_configno

Documentación

85Excelente
Cómo se puntúa
30/30README
25/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
10/10Topics — 5 topics
10/10Wiki
Datos de entrada utilizados
topicsai, legion-core, legionio, llm, ruby
has_wiki
homepage
has_readme
has_docs_dir
has_description

Seguridad

¿Son sólidas las prácticas visibles de seguridad y de cadena de suministro, sin exposición jurisdiccional de alto riesgo sin resolver?

59Moderado · 16% del índice global
Cómo se puntúa
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.5Licencia — 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 — sin datos
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
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate5,9
Excluidos de la puntuación (sin datos o no aplicable): packaging. Los pesos restantes se han renormalizado.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Es una insignia independiente y experimental — peso 0,0, de modo que se presenta por separado y no afecta a la puntuación de salud global.

58Moderado · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — AGENTS.md, CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 82 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,82
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes7940
Cómo se puntúa
0/18Arranque con un solo comando
22/22Pruebas automatizadas
11/11Configuración de lint / formato — .rubocop.yml
0/11Verificación estática de tipos
0/10Entorno reproducible
0/10Práctica demostrada con agentes — ningún commit con autoría de agente entre los últimos 100
5/8Mantenimiento automatizado — automatización de dependencias configurada, no observada en los commits muestreados
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfiles
has_dockerfileno
typed_languageno
bootstrap_files
has_devcontainerno
has_linter_config
typecheck_configs
agent_commit_share0
toolchain_manifests
dependency_bot_commit_share0
Cómo se puntúa
0/45Código verificable por tipos — Ruby sin configuración de verificación de tipos
54.8/55Tamaños de archivo manejables — 2/495 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageRuby
largest_source_bytes66.627
source_files_sampled495
oversized_source_files2

Datos clave

2estrellas de GitHub
4contribuidores
1119commits en los últimos 12 meses
0días desde el último push
100versiones publicadas
1factor bus
6issues abiertas
RubyGemsecosistemas de paquetes

Advertencias de recopilación de datos

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

Más detalle

Historial de estrellas y forks 0 ★ / 3 ⇿
0Estrellas
3Forks
2Versiones

Cuándo se añadió cada estrella y fork, recopilado de GitHub y agrupado por día. El crecimiento acumulado se sitúa justo encima de las adiciones diarias que lo componen, de modo que ambos se leen en conjunto: la acumulación orgánica sostenida no se parece en nada a un pico abrupto y efímero. Cuando esa diferencia es medible, se informa como autenticidad del crecimiento.

12233312026-042026-042026-04
Mayor 0Menor 0Parche 2
OpenSSF Scorecard 5.9 / 10
5.9agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).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
n/dPackagingpackaging 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
Dependencias directas 11
RegistroPaqueteRestricción de versiónManifiesto
RubyGemslegion-settingsGemfile
RubyGemsrack-test~> 2.0Gemfile
RubyGemsrakeGemfile
RubyGemsrspecGemfile
RubyGemsrspec_junit_formatterGemfile
RubyGemsrubocopGemfile
RubyGemsrubocop-legionGemfile
RubyGemsrubocop-legion>= 0.1.8Gemfile
RubyGemssimplecovGemfile
RubyGemssinatraGemfile
RubyGemswebmockGemfile
Todas las dependencias 22

Conjunto completo de dependencias resueltas según el grafo de dependencias de GitHub: 10 paquetes directos y 12 indirectos (transitivos). El cierre transitivo es completo cuando el repositorio incluye un lockfile.

RegistroPaqueteVersiónRelación
RubyGemslegion-settingsdirecta
RubyGemsrack-testdirecta
RubyGemsrakedirecta
RubyGemsrspecdirecta
RubyGemsrspec_junit_formatterdirecta
RubyGemsrubocopdirecta
RubyGemsrubocop-legiondirecta
RubyGemssimplecovdirecta
RubyGemssinatradirecta
RubyGemswebmockdirecta
RubyGemsconcurrent-rubyindirecta
RubyGemsevent_stream_parserindirecta
RubyGemsfaradayindirecta
RubyGemslegion-cacheindirecta
RubyGemslegion-jsonindirecta
RubyGemslegion-loggingindirecta
RubyGemslegion-transportindirecta
RubyGemslex-knowledgeindirecta
RubyGemslex-llmindirecta
RubyGemspdf-readerindirecta
RubyGemssinatra-contribindirecta
RubyGemstzinfoindirecta
Avisos de dependencias sin evaluar

El cotejo de avisos no pudo ejecutarse para este informe: No resolved dependencies carried a version and a supported ecosystem

Informe JSON sin procesar legible por máquina
{
  "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"
}

Las puntuaciones son señales, no garantías. Reflejan prácticas públicamente visibles en GitHub; no son una auditoría de código ni una garantía de seguridad.

Los datos ausentes se excluyen y los pesos se renormalizan; nunca se puntúan como cero. La metodología es versionada y abierta: métricas v1.13.0, esquema v0.27.0 — metodología completa · wiki de métricas.

Cómo se sitúa un resultado dentro del registro general: estadísticas agregadasRubyGems.