Öffentliches Register
Software-GesundheitsberichtSchema 0.27.0 · Metriken 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 Sterne⑂ 3 Forksseit März 2026Auf GitHub ansehen ↗

LegionIO/legion-llm erreicht einen Gesundheitsindex von 68 von 100 und liegt damit im Bereich Mittel. Am stärksten schneidet es bei Engineering Quality (84/100) ab, am schwächsten bei Community & Adoption (48/100). Zuletzt heute aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

68
gesamt / 100
Mittel

Software-Gesundheitsindex

Metriken werden auf einer Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr Mittel; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze 49 (Gefährdet). AI Readiness liegt außerhalb.

68
Exzellent85-100Vorbildlich; erfüllt im Wesentlichen alle geprüften Kriterien
Gut70-84Gesund; geringfügige Lücken
Mittel50-69Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Gefährdet30-49Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-29Schwerwiegende Probleme (aufgegeben, nur ein Maintainer, keine Hygiene)
VitalitätCommunity &VerbreitungNachhaltigkeit &GovernanceEngineering-QualitätSicherheitAI Readiness

Bewertungsprofil

Jede Achse ist eine Kategorie. Die Form zählt mehr als der Durchschnitt — ein gesundes Projekt füllt die gesamte Fläche, während ein Profil aus Spitzen und Kratern bedeutet, dass Stärke in einer Dimension Risiken in einer anderen verdeckt.

Eigentümerschaft

LegionIOOrganisation
23 Follower199 öffentliche Reposseit Dez. 2018

Dieses Repository wird von einer Organisation getragen — geteilte, rechenschaftspflichtige Trägerschaft, die jeden einzelnen Maintainer überdauern kann.

Paket-Ökosysteme

RegistryPaketVersionDownloads / MonatVersionenZuletzt veröffentlicht
RubyGemslegion-llm0.14.17-141vor 0 Tagen

Metriken nach Kategorie

Vitalität

Lebt das Projekt — wird Code geschrieben und werden Releases ausgeliefert?

82Gut · 22 % des Gesamtindex
Wie die Bewertung erfolgt
36/36Push-Aktualität — letzter Push vor 0 Tagen
13.2/36Commit-Rhythmus — 19/52 Wochen mit Commits
18/18Commit-Volumen — 1.119 Commits im letzten Jahr
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Verwendete Eingangsdaten
commits_last_year1.119
human_commit_share1
days_since_last_push0
active_weeks_last_year19
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 100 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 0 Tagen
27/27Release-Rhythmus — ein Release etwa alle 4 Tage
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Verwendete Eingangsdaten
releases_count100
latest_release_tagv0.14.17
releases_from_tagsnein
days_since_latest_release0
mean_days_between_releases4

Community & Verbreitung

Hat das Projekt Nutzer, Downloads, Aufmerksamkeit und ein einladendes Umfeld für Beitragende?

48Gefährdet · 18 % des Gesamtindex
Wie die Bewertung erfolgt
0/60Stars — 2 Stars
2.5/25Forks — 3 Forks
0/15Watcher — 1 Watcher
Verwendete Eingangsdaten
forks3
stars2
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Wie die Bewertung erfolgt
22.5/22.5README
22.5/22.5Lizenz — anerkannte Lizenz (Apache-2.0)
18/18CONTRIBUTING-Leitfaden
13.5/13.5Verhaltenskodex
0/7.2Issue-Vorlage
6.3/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licenseja
has_contributingja
has_issue_templatenein
has_code_of_conductja
has_pull_request_templateja
Wie die Bewertung erfolgt
47.2/80Downloads gesamt — 34.511 Downloads insgesamt über rubygems
0/20Abhängige in der Registry — von diesem Ökosystem nicht ausgewiesen
Verwendete Eingangsdaten
packageslegion-llm
dependents
ecosystemsrubygems
total_downloads34.511
monthly_downloads
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Abhängige in der Registry. Die verbleibenden Gewichte wurden renormalisiert.

Nachhaltigkeit & Governance

Überdauert das Projekt die Menschen, die es tragen — Bus-Faktor, Reaktionsfähigkeit, Trägerschaft und Paketpflege?

62Mittel · 24 % des Gesamtindex
Wie die Bewertung erfolgt
9/54Bus-Faktor — 1 Beitragende decken die Hälfte aller Commits ab
0.4/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 98 % der Commits
5.4/13.5Breite der Beitragenden — 4 Beitragende
6/10OpenSSF Scorecard: Contributors — project has 2 contributing companies or organizations -- score normalized to 6
Verwendete Eingangsdaten
bus_factor1
contributors_sampled4
top_contributor_share0,981
Wie die Bewertung erfolgt
42.8/46.8Issue-Lösungsquote — 92 % der Issues geschlossen
36.3/38.3PR-Annahme — 95/100 entschiedene PRs gemergt
0/15OpenSSF Scorecard: Code-Review — Found 0/6 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
merged_prs95
open_issues6
closed_issues65
issue_closed_ratio0,915
closed_unmerged_prs5
Wie die Bewertung erfolgt
30/30Organisatorische Trägerschaft — im Besitz einer Organisation
0/20Verifizierte Domain
9.9/25Reichweite des Inhabers — 23 Follower von LegionIO
25/25Kontohistorie — 199 öffentliche Repos, Kontoalter ca. 7 Jahre
Verwendete Eingangsdaten
followers23
owner_typeOrganization
is_verified
owner_loginLegionIO
public_repos199
account_age_days2.778

Paketpflege

100Exzellent
Wie die Bewertung erfolgt
25/25Veröffentlicht & auflösbar — 1 Paket(e) auf rubygems
35/35Veröffentlichungsaktualität — letzte Veröffentlichung vor 0 Tagen
20/20Versionshistorie — 141 veröffentlichte Versionen
20/20Nicht veraltet — aktiv, nicht veraltet oder zurückgezogen
Verwendete Eingangsdaten
packageslegion-llm
ecosystemsrubygems
any_deprecatednein
min_days_since_publish0

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

84Gut · 20 % des Gesamtindex
Wie die Bewertung erfolgt
24/24CI-Workflows — 1 Workflow(s)
24/24Tests vorhanden
16/16Linter-Konfiguration — .rubocop.yml
0/9.6Pre-Commit-Hooks
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 6 out of 6 merged PRs checked by a CI test -- score normalized to 10
Verwendete Eingangsdaten
has_cija
has_testsja
has_editorconfignein
has_linter_configja
has_precommit_confignein

Dokumentation

85Exzellent
Wie die Bewertung erfolgt
30/30README
25/25Dokumentationsverzeichnis
0/15Dokumentations-/Homepage-Site
10/10Repository-Beschreibung
10/10Topics — 5 Topics
10/10Wiki
Verwendete Eingangsdaten
topicsai, legion-core, legionio, llm, ruby
has_wikija
homepage
has_readmeja
has_docs_dirja
has_descriptionja

Sicherheit

Sind die sichtbaren Sicherheits- und Lieferkettenpraktiken belastbar, ohne ungeklärte Exposition gegenüber Hochrisikojurisdiktionen?

59Mittel · 16 % des Gesamtindex
Wie die Bewertung erfolgt
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.5Lizenz — 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 — keine Daten
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
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate5,9
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): packaging. Die verbleibenden Gewichte wurden renormalisiert.

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Ein unabhängiges, experimentelles Badge — Gewicht 0,0, es wird eigenständig ausgewiesen und verändert den Gesamt-Gesundheitswert nicht.

58Mittel · 0 % des Gesamtindex
Wie die Bewertung erfolgt
45/45Agentenanweisungen — AGENTS.md, CLAUDE.md
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 82 von 100 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share0,82
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes7.940
Wie die Bewertung erfolgt
0/18Bootstrap mit einem Befehl
22/22Automatisierte Tests
11/11Lint-/Format-Konfiguration — .rubocop.yml
0/11Statische Typprüfung
0/10Reproduzierbare Umgebung
0/10Belegte Agentenpraxis — keine von Agenten verfassten Commits unter den letzten 100
5/8Automatisierte Wartung — Abhängigkeits-Automatisierung konfiguriert, in den erfassten Commits nicht beobachtet
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfiles
has_dockerfilenein
typed_languagenein
bootstrap_files
has_devcontainernein
has_linter_configja
typecheck_configs
agent_commit_share0
toolchain_manifests
dependency_bot_commit_share0
Wie die Bewertung erfolgt
0/45Typprüfbarer Code — Ruby ohne Typprüfungs-Konfiguration
54.8/55Handhabbare Dateigrößen — 2/495 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languageRuby
largest_source_bytes66.627
source_files_sampled495
oversized_source_files2

Eckdaten

2GitHub-Sterne
4Mitwirkende
1.119Commits, letzte 12 Monate
0Tage seit letztem Push
100Releases
1Bus-Faktor
6offene Issues
RubyGemsPaket-Ökosysteme

Warnungen zur Datenerhebung

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

Weitere Details

Stern- und Fork-Verlauf 0 ★ / 3 ⇿
0Sterne
3Forks
2Releases

Wann jeder Stern und Fork hinzugefügt wurde, von GitHub erfasst und nach Tagen gruppiert. Das kumulierte Wachstum steht direkt über den täglichen Zugängen, aus denen es besteht, sodass beide gegeneinander lesbar sind: stetiger organischer Zuwachs sieht ganz anders aus als ein abrupter, kurzlebiger Ausschlag. Wo dieser Unterschied messbar ist, wird er als Wachstumsauthentizität ausgewiesen.

12233312026-042026-042026-04
Major 0Minor 0Patch 2
OpenSSF Scorecard 5.9 / 10
5.9Gesamtwert

Unabhängige, werkzeugneutrale Sicherheitsbewertung durch das quelloffene OpenSSF Scorecard. Jede Prüfung honoriert eine Sicherheits-Praxis, nicht das Werkzeug eines bestimmten Anbieters. Prüfungen, die Scorecard nicht ermitteln konnte, sind mit k. A. markiert und vom Sicherheitswert ausgeschlossen (nie als null gezählt).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
k. A.Packagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
10SASTSAST tool is run on all commits
10Security-Policysecurity policy file detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
Direkte Abhängigkeiten 11
RegistryPaketVersionsvorgabeManifest
RubyGemslegion-settingsGemfile
RubyGemsrack-test~> 2.0Gemfile
RubyGemsrakeGemfile
RubyGemsrspecGemfile
RubyGemsrspec_junit_formatterGemfile
RubyGemsrubocopGemfile
RubyGemsrubocop-legionGemfile
RubyGemsrubocop-legion>= 0.1.8Gemfile
RubyGemssimplecovGemfile
RubyGemssinatraGemfile
RubyGemswebmockGemfile
Alle Abhängigkeiten 22

Vollständig aufgelöster Abhängigkeitssatz aus dem GitHub-Abhängigkeitsgraphen: 10 direkte und 12 indirekte (transitive) Pakete. Die transitive Hülle ist vollständig, wenn das Repository eine Lockfile eincheckt.

RegistryPaketVersionBeziehung
RubyGemslegion-settingsdirekt
RubyGemsrack-testdirekt
RubyGemsrakedirekt
RubyGemsrspecdirekt
RubyGemsrspec_junit_formatterdirekt
RubyGemsrubocopdirekt
RubyGemsrubocop-legiondirekt
RubyGemssimplecovdirekt
RubyGemssinatradirekt
RubyGemswebmockdirekt
RubyGemsconcurrent-rubyindirekt
RubyGemsevent_stream_parserindirekt
RubyGemsfaradayindirekt
RubyGemslegion-cacheindirekt
RubyGemslegion-jsonindirekt
RubyGemslegion-loggingindirekt
RubyGemslegion-transportindirekt
RubyGemslex-knowledgeindirekt
RubyGemslex-llmindirekt
RubyGemspdf-readerindirekt
RubyGemssinatra-contribindirekt
RubyGemstzinfoindirekt
Abhängigkeits-Advisories nicht bewertet

Der Advisory-Abgleich konnte für diesen Bericht nicht ausgeführt werden: No resolved dependencies carried a version and a supported ecosystem

JSON-Rohbericht maschinenlesbar
{
  "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"
}

Bewertungen sind Signale, keine Garantien. Sie spiegeln öffentlich sichtbare Praxis auf GitHub wider — kein Code-Audit und keine Sicherheitsgarantie.

Fehlende Daten werden ausgeschlossen und die Gewichte neu normiert, nie als null bewertet. Die Methodik ist versioniert und offen: Metriken v1.13.0, Schema v0.27.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte StatistikenRubyGems.