Öffentliches Register
Software-GesundheitsberichtSchema 0.27.0 · Metriken 1.13.0 · 2026-07-28 01:11 UTC

metanorma / suma

Management utility for SUMA (STEP Unified Model-Based Standards Architecture)

RubyKeine Lizenz erkannt★ 1 Stern⑂ 0 Forksseit Juni 2024Auf GitHub ansehen ↗

metanorma/suma erreicht einen Gesundheitsindex von 60 von 100 und liegt damit im Bereich Mittel. Am stärksten schneidet es bei Vitality (70/100) ab, am schwächsten bei Community & Adoption (40/100). Zuletzt heute aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

60
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.

60
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

MetanormaOrganisation
95 Follower331 öffentliche Reposseit Mai 2018

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

Paket-Ökosysteme

RegistryPaketVersionDownloads / MonatVersionenZuletzt veröffentlicht
RubyGemssuma0.5.2-39vor 0 Tagen

Metriken nach Kategorie

Vitalität

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

70Gut · 22 % des Gesamtindex
Wie die Bewertung erfolgt
36/36Push-Aktualität — letzter Push vor 0 Tagen
11.1/36Commit-Rhythmus — 16/52 Wochen mit Commits
18/18Commit-Volumen — 102 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_year102
human_commit_share1
days_since_last_push0
active_weeks_last_year16
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 1 Releases veröffentlicht
16.2/36Release-Aktualität — letztes Release vor 252 Tagen
12.6/27Release-Rhythmus — Rhythmus unbekannt (nur ein Release)
0/10OpenSSF Scorecard: Signed-Releases — keine Daten
Verwendete Eingangsdaten
releases_count1
latest_release_tagv0.2.0
releases_from_tagsnein
days_since_latest_release252
mean_days_between_releases
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: Signed-Releases. Die verbleibenden Gewichte wurden renormalisiert.

Community & Verbreitung

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

40Gefährdet · 18 % des Gesamtindex
Wie die Bewertung erfolgt
0/60Stars — 1 Stars
0/25Forks — 0 Forks
4.7/15Watcher — 8 Watcher
Verwendete Eingangsdaten
forks0
stars1
watchers8
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Wie die Bewertung erfolgt
22.5/22.5README
0/22.5Lizenz — keine Lizenzdatei erkannt
18/18CONTRIBUTING-Leitfaden
13.5/13.5Verhaltenskodex
0/7.2Issue-Vorlage
6.3/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licensenein
has_contributingja
has_issue_templatenein
has_code_of_conductja
has_pull_request_templateja
Wie die Bewertung erfolgt
46.5/80Downloads gesamt — 29.667 Downloads insgesamt über rubygems
0/20Abhängige in der Registry — von diesem Ökosystem nicht ausgewiesen
Verwendete Eingangsdaten
packagessuma
dependents
ecosystemsrubygems
total_downloads29.667
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?

66Mittel · 24 % des Gesamtindex
Wie die Bewertung erfolgt
9/54Bus-Faktor — 1 Beitragende decken die Hälfte aller Commits ab
9.7/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 57 % der Commits
6.8/13.5Breite der Beitragenden — 5 Beitragende
10/10OpenSSF Scorecard: Contributors — project has 5 contributing companies or organizations
Verwendete Eingangsdaten
bus_factor1
contributors_sampled5
top_contributor_share0,569
Wie die Bewertung erfolgt
36.4/46.8Issue-Lösungsquote — 78 % der Issues geschlossen
35/38.3PR-Annahme — 54/59 entschiedene PRs gemergt
0/15OpenSSF Scorecard: Code-Review — Found 0/16 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
merged_prs54
open_issues10
closed_issues35
issue_closed_ratio0,778
closed_unmerged_prs5
Wie die Bewertung erfolgt
30/30Organisatorische Trägerschaft — im Besitz einer Organisation
0/20Verifizierte Domain
14.3/25Reichweite des Inhabers — 95 Follower von metanorma
25/25Kontohistorie — 331 öffentliche Repos, Kontoalter ca. 8 Jahre
Verwendete Eingangsdaten
followers95
owner_typeOrganization
is_verified
owner_loginmetanorma
public_repos331
account_age_days2.993

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 — 39 veröffentlichte Versionen
20/20Nicht veraltet — aktiv, nicht veraltet oder zurückgezogen
Verwendete Eingangsdaten
packagessuma
ecosystemsrubygems
any_deprecatednein
min_days_since_publish0

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

70Gut · 20 % des Gesamtindex
Wie die Bewertung erfolgt
24/24CI-Workflows — 2 Workflow(s)
24/24Tests vorhanden
16/16Linter-Konfiguration — .rubocop.yml
0/9.6Pre-Commit-Hooks
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 8 out of 8 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
Wie die Bewertung erfolgt
30/30README
0/25Dokumentationsverzeichnis
0/15Dokumentations-/Homepage-Site
10/10Repository-Beschreibung
0/10Topics
10/10Wiki
Verwendete Eingangsdaten
topics
has_wikija
homepage
has_readmeja
has_docs_dirnein
has_descriptionja

Sicherheit

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

46Gefährdet · 16 % des Gesamtindex

Sicherheitslage

46Gefährdet
Wie die Bewertung erfolgt
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.5/2.5CI-Tests — 8 out of 8 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/16 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 5 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
0/2.5Lizenz — license file not 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
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — keine Daten
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate4,6
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): packaging, signed_releases. 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.

55Mittel · 0 % des Gesamtindex
Wie die Bewertung erfolgt
45/45Agentenanweisungen — CLAUDE.md
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 76 von 100 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share0,76
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes8.037
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
0/8Automatisierte Wartung — keine automatisierten Abhängigkeits-Updates 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
55/55Handhabbare Dateigrößen — 0/101 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languageRuby
largest_source_bytes11.805
source_files_sampled101
oversized_source_files0

Eckdaten

1GitHub-Sterne
5Mitwirkende
102Commits, letzte 12 Monate
0Tage seit letztem Push
1Releases
1Bus-Faktor
10offene 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

OpenSSF Scorecard 4.6 / 10
4.6Gesamtwert

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-28 01:11 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
10CI-Tests8 out of 8 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/16 approved changesets -- score normalized to 0
10Contributorsproject has 5 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
0Licenselicense file not 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
0Security-Policysecurity policy file not detected
k. A.Signed-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
Direkte Abhängigkeiten 10
RegistryPaketVersionsvorgabeManifest
RubyGemscanonGemfile
RubyGemsmetanormaGemfile
RubyGemsnokogiriGemfile
RubyGemsopenssl~> 3.0Gemfile
RubyGemsrakeGemfile
RubyGemsrspecGemfile
RubyGemsrubocopGemfile
RubyGemsrubocop-performanceGemfile
RubyGemsrubocop-rakeGemfile
RubyGemsrubocop-rspecGemfile
Alle Abhängigkeiten 19

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

RegistryPaketVersionBeziehung
RubyGemscanondirekt
RubyGemsmetanormadirekt
RubyGemsnokogiridirekt
RubyGemsopenssldirekt
RubyGemsrakedirekt
RubyGemsrspecdirekt
RubyGemsrubocopdirekt
RubyGemsrubocop-performancedirekt
RubyGemsrubocop-rakedirekt
RubyGemsrubocop-rspecdirekt
RubyGemsexpressirindirekt
RubyGemsglossaristindirekt
RubyGemslutaml-modelindirekt
RubyGemsplurimathindirekt
RubyGemsruby-progressbarindirekt
RubyGemsrubyzipindirekt
RubyGemssvg_conformindirekt
RubyGemstable_tennisindirekt
RubyGemsthorindirekt
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": [],
      "is_fork": false,
      "size_kb": 689,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Ruby": 322720,
        "Shell": 131
      },
      "pushed_at": "2026-07-28T01:06:04Z",
      "created_at": "2024-06-06T08:50:42Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-28T01:06:06Z",
      "description": "Management utility for SUMA (STEP Unified Model-Based Standards Architecture)",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": null,
      "primary_language": "Ruby",
      "significant_languages": [
        "Ruby"
      ]
    },
    "owner": {
      "blog": "https://www.metanorma.org",
      "name": "Metanorma",
      "type": "Organization",
      "login": "metanorma",
      "company": null,
      "location": null,
      "followers": 95,
      "avatar_url": "https://avatars.githubusercontent.com/u/39362184?v=4",
      "created_at": "2018-05-17T05:14:19Z",
      "is_verified": null,
      "public_repos": 331,
      "account_age_days": 2993
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2025-11-17T03:02:34Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "222b291f5088c8c23031d0f3641f1fbea1b44569",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.5.2",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2026-07-28T01:06:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "147d18185ec3f5bb5a8bd7166e4e005b75bcc38e",
          "body": "…rom output path",
          "is_bot": false,
          "headline": "Fix plain schema export: category level (resources/modules) removed f…",
          "author_name": "KW Kwan",
          "author_login": "kwkwan",
          "committed_at": "2026-07-28T00:35:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a2f13367926dfc96961e2479ef05094adb5ff9c4",
          "body": "…release_command bundle install) (#104)\n\nrequest-checks: true",
          "is_bot": false,
          "headline": "cimas: sync master templates (rubocop todo inherit fix + release.yml …",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-12T11:12:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2637cae55cebef50c213d0ae36d782d0428dcaa9",
          "body": null,
          "is_bot": false,
          "headline": "version bump",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-06T10:36:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "40277af1569b17637ab8ba34b031cf143e462bd5",
          "body": "Rubocop was reporting 552 offenses on main: the cimas-generated .rubocop.yml\ndid not reference .rubocop_todo.yml at all, so the todo was inert. Regenerate\nthe todo (--no-exclude-limit) to grandfather the legacy offenses, and list it\nLAST in inherit_from so it overrides the remote oss-guides config (\n[…]\n manually\"); the next\ncimas-sync will drop this inherit_from ordering and reintroduce the offenses.\nThe durable fix belongs in the cimas rubocop template (emit .rubocop_todo.yml\nlast in inherit_from).",
          "is_bot": false,
          "headline": "chore: regenerate rubocop todo and apply it in inherit_from",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-06T10:34:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6fe4b2f54493bf03147bab04fc0eeba2afb85624",
          "body": "Cimas sync 2026-07-05: propagate #300 gaps + accumulated template drift",
          "is_bot": false,
          "headline": "Merge pull request #102 from metanorma/cimas-sync-2026-07-05",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-06T10:27:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0e618eb3e8e339f6d651aad6d6dac4f572dbaffe",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into cimas-sync-2026-07-05",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-06T06:06:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e14d1f279c814eabff481bcb9c20cfd267681c0c",
          "body": "Memory-bounded staged collection build (opt-in)",
          "is_bot": false,
          "headline": "Merge pull request #103 from metanorma/feature/staged-collection-build",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-06T06:05:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "417e02e3265d7a5c022883c834623e5191df1fd9",
          "body": "…der)",
          "is_bot": false,
          "headline": "style: satisfy rubocop (extract helpers, predicate naming, subject or…",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-06T02:26:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3f551face872b566581d7ef50d3b5903f139adc0",
          "body": "Compile each collection member in its own OS process (preserving cross-document\nreferences as stubs into a content-addressed store), sequentially, then\nreinflate the stored stubs into the final collection. Peak memory is bounded by\na single member instead of the whole collection; the default single-\n[…]\nstaged / staged: true).\n\nNeeds the metanorma#578 engine render options (preserve_unresolved:,\nartifact_store_dir:, reinflate:); Gemfile points metanorma at that feature\nbranch until 2.5.0 is released.",
          "is_bot": false,
          "headline": "feat: opt-in memory-bounded staged collection build (suma#94)",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-06T01:42:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "548e996d2d1b4acd0cd7040c0624f38cfc8a91ea",
          "body": "… 16 from plugin drift)\n\n.rubocop_todo.yml had grown to 368 lines with entries for 525\noffenses, but many entries were stale — Ronald's ongoing refactoring\n(LinkValidator split, NoteProcessor extract, etc.) removed a lot of\nthe offending code without regenerating the todo. Regenerated on\ncurrent mai\n[…]\nttps://github.com/metanorma/suma/pull/102) that failed CI\nwith these offenses should pass on retry.\n\nSurfaced by the 2026-07-05 cimas-sync wave; recorded in the SSOT\nunder the failed-PR sweep section.",
          "is_bot": false,
          "headline": "chore: regenerate .rubocop_todo.yml (drops 193 stale exclusions, adds…",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-05T12:16:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a07c418e6bd48c363eb93f27af9d15b00ff3b0a7",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.5.0",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2026-07-05T01:03:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cafac6ab86238c9f7e5423445e4f06694f31f857",
          "body": "validate_deep_path was ~80 lines with a case statement dispatching\non Expressir node type (Entity → attribute lookup, Type → enum /\nunderlying-type navigation). Adding a new navigable EXPRESS construct\n(functions, procedures) meant editing this method — an OCP violation.\n\nAdd Suma::LinkValidator::St\n[…]\n in REGISTRY — no edits\nto existing Steps or to validate_deep_path.\n\nNew step_spec covers each Step in isolation (no full-pipeline\nscaffolding required). Existing link_validator_spec passes\nunchanged.",
          "is_bot": false,
          "headline": "refactor: split LinkValidator#validate_deep_path into per-type Steps",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-05T00:59:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4557754e366037774b833814050ab8909e515219",
          "body": "EengineConverter's constructor read the XML file:\n\n  def initialize(xml_path, schema_name)\n    @xml_path = xml_path\n    @schema_name = schema_name\n    @xml_content = File.read(xml_path)\n  end\n\nI/O in constructors is a recognised anti-pattern: objects cannot be\ninstantiated without a real file on dis\n[…]\nl_content)\n\nSchemaComparer reads the file and passes content. Updated spec passes\na string and no longer touches the filesystem during construction.\n\nAlso drops the unused @xml_path instance variable.",
          "is_bot": false,
          "headline": "refactor: move File.read out of EengineConverter constructor",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-05T00:59:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4a61e8d68cb61dce82bb1a64c1d6d12511cf3629",
          "body": "TermExtractor carried the entire note-cleaning pipeline as eleven\nprivate methods plus the REDUNDANT_NOTE_REGEX constant. Note\nprocessing is a self-contained concern: turn raw entity.remarks into\na list of clean DetailedDefinition notes for the localized concept.\n\nAdd Suma::NoteProcessor: pure input\n[…]\n → /\\.\\n/.\n\nNoteProcessor has its own spec covering each cleaning rule\n(redundant opening, image refs, double-angle brackets, see-tail\nstripping, definition dedup, list preservation, xref conversion).",
          "is_bot": false,
          "headline": "refactor: extract NoteProcessor from TermExtractor",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-05T00:59:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "66df3c33d0178b56a9cec5cbbda86d8827d2727d",
          "body": "…ster\n\nThe double-Thor pattern (Core delegates to Cli::ExtractTerms.start, which reparses ARGV) was broken because Core has check_unknown_options! enabled via ThorExt::Start. This caused Core to reject any options declared only on the inner Thor class — e.g. --urn, --language-code, --exclude-paths, \n[…]\nice classes (TermExtractor, RegisterManifestGenerator) directly, bypassing the inner Thor wrapper. The inner classes (Cli::ExtractTerms, Cli::GenerateRegister) remain as backwards-compat entry points.",
          "is_bot": false,
          "headline": "fix(cli): declare options on Core for extract-terms and generate-regi…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-05T00:59:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5dacaaf6f1e10dc78300207c0a8ecb78b8348257",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.4.0",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2026-07-05T00:27:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6eb84fd78fc1ee96b645de7d9b7fef227d1ebfef",
          "body": "CodeQL flagged the COMMENT_PATTERN regex /\\(\\*\"(.*?)\\n\\*\\)/m as\npolynomial-time (rb/polynomial-redos). The non-greedy .* with /m is\nvulnerable to catastrophic backtracking on adversarial input starting\nwith (*\" and repeating (*\"a.\n\nReplace the single m-mode regex with a 2-pass String#index scan:\nfind the next COMMENT_START, find the next COMMENT_END after it,\nslice the body. Linear time, no backtracking. Same idempotence and\nwhitespace-normalisation behaviour; existing specs unchanged.",
          "is_bot": false,
          "headline": "fix: clear CodeQL ReDoS alert in ExpressReformatter comment extraction",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-04T23:57:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c9a97cfd7e6e055a2b443cb399842a63c9eb2473",
          "body": "Two coupled changes at the SchemaExporter seam:\n\n(1) Single-parse: SchemaCollection#compile previously built an\nExpressSchema for every schema (stored in @schemas) and then passed\nthe raw manifest entries to SchemaExporter, which constructed a\nsecond ExpressSchema per file and re-parsed. Each schema\n[…]\nIP). Classification\nlives in the CLI adapter, which uses SchemaCategory.for_schema to\nset the right output subdirectory.\n\nUpdated specs use real ExpressSchema instances instead of Structs at\nthe seam.",
          "is_bot": false,
          "headline": "refactor: SchemaExporter accepts loaded ExpressSchema objects",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-04T23:57:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a1e1cdbd973adcc36608a47298aaa2c8d763dec3",
          "body": "Cli::CheckSvgQuality (172 lines) interleaved three concerns: file\ndiscovery (recursive Pathname glob), validation orchestration\n(SvgConform::Validator + per-file Report construction + progress\nreporting), and presentation (filter chain + formatter dispatch).\nNone of the orchestration was reachable f\n[…]\n_report. Both share the scanner.\n\nFormatters (Terminal/Json/Yaml) are unchanged; they were already\ncorrectly seamed. New scanner_spec exercises both scan and scan_file\nagainst real svg_conform output.",
          "is_bot": false,
          "headline": "refactor: extract SvgQuality::Scanner from CLI",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-04T23:57:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1518a72572d4e1046a466c029e32f5386bd18503",
          "body": "Cli::Reformat embedded genuine EXPRESS transformation logic in a\nThor method body: comment-block extraction via regex, whitespace\nnormalisation, no-op detection, and conditional file rewrite. The\ncontent transformation was untestable without Thor and unreachable\nfrom any future programmatic caller.\n\n[…]\novery, read/transform/write. The transformation itself is\ntestable as a pure function.\n\nThe transform is idempotent: reformatting already-reformatted\ncontent returns changed?: false. Verified by spec.",
          "is_bot": false,
          "headline": "refactor: extract ExpressReformatter from CLI",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-04T23:57:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bbe1626758fa0ae14e31bec60022ef15777a6008",
          "body": "Cli::ValidateLinks (169 lines) was a Thor class whose body was the\nimplementation: nine private methods doing file discovery, schema\nloading, link extraction, validation orchestration, and result\nformatting. None of it was reachable from a spec without invoking\nThor.\n\nAdd Suma::LinkValidation: deep \n[…]\n previously had its own copy that had already drifted slightly.\n\nTests use real Expressir parsing on real fixtures; a NullProgress\nadapter lets the service run without the ruby-progressbar dependency.",
          "is_bot": false,
          "headline": "refactor: extract LinkValidation deep module from CLI",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-04T23:57:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ae814e96ec82224b653ce3efabc46c545b21dfb5",
          "body": "TermExtractor classified schemas three different ways in one file:\nsuffix-match on schema.id, filename regex for arm/mim/bom, and a\nstring-based type-switch in generate_entity_definition. Each path\nreimplemented what ExpressSchema::Type and SchemaCategory already own\nas the canonical taxonomy.\n\nAdd \n[…]\nement all disappear.\n\nLocality: adding a new schema type touches one Hash entry, not four\ncode sites. Coverage: :core_model and :standalone schemas no longer\nraise the \"unsupported schema_type\" error.",
          "is_bot": false,
          "headline": "refactor: route TermExtractor through TermClassification",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-04T23:57:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8cb91be8e84b558d28c9e101604ca6935712928a",
          "body": "request-checks: true",
          "is_bot": false,
          "headline": "Cimas sync 2026-07-05: propagate #300 gaps + accumulated template drift",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-07-04T16:36:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1aadf1c63210672e95969f1d0f230ebdfd12ad25",
          "body": "TODO.* directories and TODO*.md files are local planning scratch\nthat must never be committed. Collapses the prior explicit\nper-directory list to a single /TODO* pattern so any future TODO\nscratch path is covered.",
          "is_bot": false,
          "headline": "chore: gitignore /TODO* scratch dirs and files",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-04T01:58:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ce4be8ac002b28901deefe4285cf466350759bc6",
          "body": "The Ruby usage examples referenced the old class-method Processor.run\nAPI and a Suma::SchemaConfig::Config class that does not exist in the\ncodebase. Both are pre-refactor leftovers.\n\n- Processor.run(...) -> Processor.new(...).run\n- Suma::SchemaConfig::Config -> Expressir::SchemaManifest.from_file\n-\n[…]\nSchemaTemplate composition)\n- Document the code-style rules enforced throughout lib/suma/: autoload\n  only, no send / instance_variable_set / respond_to?, Utils.log to\n  $stderr with SUMA_DEBUG gating",
          "is_bot": false,
          "headline": "docs: update README to current API and add architecture section",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-03T03:47:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9230186d40ef1b38c66518663357b39d3e136004",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.3.0",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2026-07-03T03:32:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "05633e491470f846d60e7eb9c333bab5d386d1a1",
          "body": "The previous fix used [^>]+ for the display half, which CodeQL still\nflagged as polynomial because that class can match characters that\nalso appear in the preceding [\\\\w.]+ ref half (overlap creates\nambiguous backtracking).\n\nReplace with [\\\\w. ][\\\\w. ]* — word chars, dots, and spaces only.\nThis is what display text actually contains in practice (entity IDs,\napplication object names, etc.) and excludes the comma/angle-bracket\npunctuation that caused the overlap.",
          "is_bot": false,
          "headline": "fix: tighten express xref display char class to clear CodeQL ReDoS alert",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "393ef24a2d356dcdb005a3737b170739ed80aa11",
          "body": "CodeQL flagged express_reference_to_mention and convert_express_xref\nfor polynomial regular expressions on uncontrolled data (entity\nremarks). Replace ([^,]+) and (.*) captures with tighter character\nclasses that match what EXPRESS identifiers actually contain:\n\n- Reference half: [\\\\w.]+ matches sch\n[…]\np to the closing >> (still\n  permissive enough for free-form display text)\n\nThe new patterns are linear-time and reject pathological inputs that\npreviously could have caused catastrophic backtracking.",
          "is_bot": false,
          "headline": "fix: anchor EXPRESS xref regexes to word chars to avoid ReDoS",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "03b3fc4065db093d0c66ece59c42f5caa446a501",
          "body": "…tion)\n\nIn glossarist 2.8.18+, ManagedConcept#id returns the UUID rather than\nthe human-readable identifier we passed in via id=. The human-readable\nidentifier now lives exclusively on data.id. The UUIDv5 shape check\nremains; the inequality check moves to data.id which is the actual\nschema.entity string we set.",
          "is_bot": false,
          "headline": "test: compare concept.uuid against data.id (glossarist 2.8.18+ conven…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "337b92d176ae0f03eac15bd6982ebc9737ef241c",
          "body": "Add dedicated spec files for every previously-untested class and lock\nin behaviour for the new value objects and services:\n\n- spec/suma/schema_category_spec.rb: SchemaCategory.for_type / for_schema\n  mapping, ALL ordering, member? predicate\n- spec/suma/urn_spec.rb: wildcard stripping, mid-string wil\n[…]\ngister_generator_spec.rb and\nspec/schema_naming_spec.rb (renamed/moved under spec/suma/).\n\nNo doubles; uses real instances, Structs, and Class.new for coercion\ntests. Total examples: 290, all passing.",
          "is_bot": false,
          "headline": "test: comprehensive spec coverage for new and existing classes",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e01b3afc16caafd9e46ae722f5e5d29ac903fa67",
          "body": "- README URN examples now reflect the current ISO 10303-2 SMRL data\n  edition (ed-2). Edition is fully configurable via the --urn CLI option.\n- Document the URN component structure with an ed-3 / French example\n  to make the configurability explicit.\n- CLAUDE.md architecture section updated for the \n[…]\nValidator.\n- Document the code-style rules now enforced codebase-wide: autoload\n  (no require_relative), no send/instance_variable_set/respond_to,\n  Utils.log writes to $stderr with SUMA_DEBUG gating.",
          "is_bot": false,
          "headline": "docs: edition-2 URN examples and updated architecture notes",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "94b6ccda54e092f4259a36246318a87426744414",
          "body": "…erser + SchemaDiscovery\n\nCollectionManifest previously mixed a lutaml-model data model with\nimperative tree-walking logic. Split into three MECE concerns:\n\n- CollectionManifest: pure data model (attributes, YAML mappings,\n  schema_config accessor). No imperative methods.\n- ManifestTraverser: tree-w\n[…]\nbuild_doc_entries, build_added_manifest).\n\nProcessor and SchemaCollection updated to construct a ManifestTraverser\naround the manifest instead of calling imperative methods on the data\nmodel directly.",
          "is_bot": false,
          "headline": "refactor: decompose CollectionManifest into data model + ManifestTrav…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9a5747634efb8f3f1913b1bcaeb12fa2ef0d9925",
          "body": "…emaCompiler\n\nSplit the SchemaAttachment/SchemaDocument inheritance hierarchy into\nthree focused components:\n\n- SchemaTemplate::Plain and SchemaTemplate::Document: pure renderers\n  that emit the AsciiDoc body for one schema (no I/O, no schema\n  knowledge). Document adds cross-reference anchors and X\n[…]\nates are\ntestable as pure functions, the compiler is the only class that owns\nfile I/O for adoc/config, and adding a new output flavour means adding\na new template class without touching the compiler.",
          "is_bot": false,
          "headline": "refactor: replace SchemaAttachment/Document with SchemaTemplate + Sch…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dfb892693f9f8ef4f3b1be0c94e291f091f1c662",
          "body": "RegisterManifestGenerator reads an EXPRESS schema manifest and emits a\nGlossarist v3 register.yaml with hierarchical sections:\n\n- Top-level groups per SchemaCategory (Resources, Application Modules,\n  Business Object Models, Core Model, Other)\n- Child sections named via SchemaNaming.prefixed_name (e\n[…]\nges\n\nRenamed from RegisterGenerator to mirror SchemaManifestGenerator and\nthe purpose of the file (producing a register.yaml).\n\nCLI: suma generate-register SCHEMA_YAML OUT_DIR -u URN --id ID --ref REF",
          "is_bot": false,
          "headline": "feat: hierarchical register.yaml generator with URN-aware sections",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c2223d3dff0c44e71b8c493656e4cb38168aab6c",
          "body": "- Consolidate schema-type detection into ExpressSchema::Type.classify\n  (id suffix + path segment); single source of truth used by\n  SchemaExporter, SchemaCategory, RegisterManifestGenerator, TermExtractor\n- Add SchemaCategory value object mapping Type to category identity\n  (id, label, prefix, type\n[…]\nlls that delegate\n- TermExtractor now assigns stable UUIDv5 identifiers and populates\n  ConceptSource#id for cite-key lookups\n- SchemaExporter uses SchemaCategory.for_schema to derive output directory",
          "is_bot": false,
          "headline": "refactor: unify schema classification and extract service objects",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a205b8e811dd14496ec70bf3f5e753b94737debb",
          "body": "- Replace require_relative with Ruby autoload throughout lib/suma/;\n  define parent-namespace autoload files (lib/suma/eengine.rb,\n  lib/suma/cli/core.rb) so children lazy-load\n- Split lib/suma/cli.rb into namespace + Cli::Core dispatcher; delegate\n  subcommands to Cli::Build, Cli::Export, Cli::Comp\n[…]\n(compile, output_directory,\n  schemas_all_path)\n- Utils.log now writes to $stderr by default with SUMA_DEBUG gating\n- Add svg_quality/formatters.rb parent namespace for terminal/json/yaml\n  formatters",
          "is_bot": false,
          "headline": "refactor: autoload CLI namespace and instance-based Processor",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "321a31d1f15a17bee8075525c3991fa63203d69e",
          "body": "- Exclude planning scratch dirs (TODO.clean/, TODO.cleanup/,\n  TODO.refactor/, TODO.remaining/) and vendored *.gem files from git\n- Use rubygems sources for metanorma deps (CI-compatible)\n- Bump glossarist to >= 2.8.7 for Glossarist v3 + UUIDv5 support\n- Regenerate .rubocop_todo.yml via rubocop --auto-gen-config",
          "is_bot": false,
          "headline": "chore: refresh gitignore, dependencies, and rubocop baseline",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0b62773a74c3bdfd810e0f18ec52310b17140178",
          "body": "…r.yaml\n\nRegisterGenerator reads the EXPRESS schema manifest and emits a\nGlossarist v3 register.yaml with hierarchical sections:\n\n  sections:\n    - id: resources\n      names: {eng: Resources}\n      children: [topology_schema, action_schema, ...]\n    - id: modules\n      names: {eng: Application Modul\n[…]\nication (DRY),\n  delegates naming to SchemaNaming (OCP), orders resources before\n  modules.\n- CLI: 'suma generate-register' command added.\n- 30 specs covering naming edge cases and register structure.",
          "is_bot": false,
          "headline": "feat: add RegisterGenerator and SchemaNaming for hierarchical registe…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-07-02T17:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0d71beba0710af12d85dea38e1eb77d3510d29d0",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.2.6",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2026-05-12T03:32:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e2aa442b349ee852921957ceec26b772716f5527",
          "body": "Add explicit permissions blocks to rake.yml and release.yml\nfollowing metanorma/ci best practices.\n\nCloses #88",
          "is_bot": false,
          "headline": "chore: add permissions to CI workflows (Cimas sync)",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-05-12T03:22:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f5063772e0b274b371aea9596d6f978c84e544b0",
          "body": null,
          "is_bot": false,
          "headline": "fix: use GitHub source for metanorma-plugin-lutaml (CI-compatible)",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-05-12T03:02:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d186c854440a41fdccf599f5db8316c35b864dd8",
          "body": "…ubocop",
          "is_bot": false,
          "headline": "fix: update Gemfile for lutaml-model 0.8.x compat, fix specs, clean r…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-05-12T03:02:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b56d564d55787f42a1cef49ec61f670f202df460",
          "body": "…ossarist",
          "is_bot": false,
          "headline": "fix: resolve gemspec duplicate lutaml-model dependency and missing gl…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-05-12T03:02:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b83e9e01764097c4db586928bfdf6168d69cf479",
          "body": "- Add error hierarchy (SchemaNotFoundError, CompilationError, EengineNotAvailableError)\n- Replace all exit/abort calls with proper exception raising\n- Remove all respond_to? and send() calls for proper OOP typing\n- Fix Expressir API references (Expressir::Express::Entity/Type -> Expressir::Model::De\n[…]\n, commented-out blocks across all files\n- Fix schema_exporter fixture paths (relative to manifest file)\n- Add specs for SchemaIndex, SchemaComparer, TermExtractor, Processor (121 examples, 0 failures)",
          "is_bot": false,
          "headline": "refactor: codebase cleanup for lutaml-model 0.8.0 compatibility",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-05-12T03:02:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3e05f3251660e87e29d32bbaea03d82c289b2b47",
          "body": "Add new CLI command to check SVG file quality using svg_conform library.\nSupports batch directory scanning and single file analysis with detailed\nerror breakdown.\n\nFeatures:\n- Batch scanning with progress output and quality report\n- Single file analysis with detailed error grouping by requirement ty\n[…]\nsorting/filtering\n- lib/suma/svg_quality/formatters/*.rb - output formatters\n\nDocumentation:\n- Added check_svg_quality command section to README.adoc\n- Updated suma.gemspec with svg_conform dependency",
          "is_bot": false,
          "headline": "feat: add check_svg_quality command for SVG validation",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-05-12T03:02:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "65aada0c639527b5470b0859fe2f2f2a47e8fd0c",
          "body": null,
          "is_bot": false,
          "headline": "feat: update lutaml-model to 0.8.0",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2026-05-12T03:02:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a3532262f8c7e937a008a6e375d6c040301738b9",
          "body": null,
          "is_bot": false,
          "headline": "update to Relaton 2.0: metanorma/metanorma-standoc#1164",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-04-13T12:37:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "686911659ee15dffaf9deebb5306c086073ef3bb",
          "body": null,
          "is_bot": false,
          "headline": "update to Relaton 2.0: metanorma/metanorma-standoc#1164",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2026-04-13T12:05:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1917e94e2d170ce5165692344a0a93ae764f05a7",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.2.4",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2026-02-04T01:44:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aa8239d25104240a828310823b20cb0a5af162f2",
          "body": null,
          "is_bot": false,
          "headline": "Update gem dependency",
          "author_name": "KW Kwan",
          "author_login": "kwkwan",
          "committed_at": "2026-02-04T01:35:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4bac757ae5474fda088c7e6f583815983fc15603",
          "body": null,
          "is_bot": false,
          "headline": "Fix wrong number of arguments",
          "author_name": "KW Kwan",
          "author_login": "kwkwan",
          "committed_at": "2026-01-30T03:54:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1a07f819220eba18bc3e217213e3e210024e678a",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.2.3",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2026-01-08T03:25:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "19dbd1b89d265e425b6d9a9ce92bc62d25aa0aa1",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-12-18T05:42:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "966093f9a7d9d5a5fe64a23e244e6610054e4d86",
          "body": null,
          "is_bot": false,
          "headline": "chore: fix openssl",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-12-18T05:42:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba6f97c88f644f7387e8eedc72f117d758203a76",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-12-18T05:42:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d3b14c41de0c87d75908bb7049b70704ab936818",
          "body": null,
          "is_bot": false,
          "headline": "fix: harmonize plain schema output files path, fixes #78",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-12-18T05:42:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b8fb7aaaa8b5693c010d7aaf6688282b2d4974e5",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.2.2",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2025-12-11T06:17:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fbd043dd9c082e6aad7c52701b6ec04562b3bba7",
          "body": null,
          "is_bot": false,
          "headline": "fix: make expressir commands work",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-12-11T06:10:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "82dd60ab7f234b8be8b544cea093ef5acc4e3fcf",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.2.1",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2025-12-11T04:04:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a154d21f141daf7eeb799e04ecf7802ade65885e",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-12-11T04:02:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "994d9682898c100e4fcab56e9075b160a7e92eb3",
          "body": "… fixes #75",
          "is_bot": false,
          "headline": "feat: remove `validate ascii` command, moved to lutaml/expressir#278,…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-12-11T04:02:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f09b0f1ba6a3a6cb506b7bbef0787e3c274c0832",
          "body": null,
          "is_bot": false,
          "headline": "gemfile, inane validation error",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2025-11-03T09:44:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "76599c208c97f50c1d177407290358d66af7597c",
          "body": null,
          "is_bot": false,
          "headline": "gemfile",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2025-11-03T09:39:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "06cdfca48c4439fffd6168350c536a4af5abd1f4",
          "body": null,
          "is_bot": false,
          "headline": "version bump",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2025-11-03T09:20:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "01fbfe4bac72d91a779b9d39799165bf1ed6022a",
          "body": "Fix suma dependencies",
          "is_bot": false,
          "headline": "Merge pull request #72 from metanorma/fix-suma-dependencies",
          "author_name": "Nick Nicholas",
          "author_login": "opoudjis",
          "committed_at": "2025-11-03T02:08:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "34b89c5528e81f24e36c1dd013d283f4f83372b7",
          "body": null,
          "is_bot": false,
          "headline": "Fix suma dependencies",
          "author_name": "KW Kwan",
          "author_login": "kwkwan",
          "committed_at": "2025-10-31T07:17:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3034c113c122a9b9aa53d31e202414930bb3c71f",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.1.26",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2025-10-16T11:13:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5541a219e900519e1ddf4f241acdd539bd1faa95",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-16T11:08:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eb10f0e977ae65d1b3ebedd133c01b4fc23cd804",
          "body": null,
          "is_bot": false,
          "headline": "feat: update to expressir 2.1.29",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-16T11:08:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "499d366e64af5eb1ed193bfaceba3581f0b5edc8",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.1.25",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2025-10-15T10:04:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "525300b60fbfcbb6198dcab8b5c3c9a1df33cca9",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-15T10:02:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f0f2577e6e12d8e10116c31930c37f463cbc6c5f",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-15T10:02:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a689e4ed9563886fbfd914a4d2db17ff40e42819",
          "body": null,
          "is_bot": false,
          "headline": "feat: suma compare command for EXPRESS schema comparison",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-15T10:02:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83a8487029837d2b5c214ccf9009097482051352",
          "body": "…, fixes #68",
          "is_bot": false,
          "headline": "fix: fix \"[NameError] uninitialized constant Suma::Cli::Export\" error…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-15T10:02:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f3bd5a185197f7f5c6cb493632272a95038df9d7",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.1.24",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2025-10-12T09:30:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f3a6bc4342814d76bc411946414b12b13402410a",
          "body": null,
          "is_bot": false,
          "headline": "fix: duplicated schema type prefixes in paths, fixes #66",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-12T09:28:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d62d3e311ce4e190a79f826ca2030e06a03f8f9b",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-12T08:51:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7b5e743b9765538751a123baf6476b48a5abd487",
          "body": null,
          "is_bot": false,
          "headline": "chore: update rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-12T08:51:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1358de89da183322856b94a7d96f46546085f499",
          "body": "…ded), closes #41",
          "is_bot": false,
          "headline": "chore: add comments for schema manifest creation (no code changes nee…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-12T08:51:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4034a9d9a1875a06ad165d626e74ee016b3bfef2",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-11T10:15:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f5b41664563b619c4ceec81f7dce4d7f6c7fd418",
          "body": "…ble, fixes #33",
          "is_bot": false,
          "headline": "feat: add `suma expressir` subcommand to make coverage feature availa…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-11T10:15:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1c9aa438a467188f9ad4bbfb8b6de4b82582b9c3",
          "body": "…ode scanning alert #3",
          "is_bot": false,
          "headline": "fix: ReDoS vulnerability in ExpressSchema#type method, fixes GitHub c…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-09T16:16:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "066624bdd5b7593ae38cbae3072b6c6b4d368e13",
          "body": "…ode scanning alert #3",
          "is_bot": false,
          "headline": "fix: ReDoS vulnerability in ExpressSchema#type method, fixes GitHub c…",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-09T16:16:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "29df7e55521e7fac0782e570ae822123950483e4",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-09T16:16:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4352a64c4591e89c9d890ce3de5082989510ae2e",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-09T16:16:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "630dc1510d37d59cbc1bfe5b9838149ffeba59c1",
          "body": null,
          "is_bot": false,
          "headline": "chore: rename \"plain EXPRESS\" to \"standalone EXPRESS\"",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-09T16:16:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "75b512a039e6a48003444c47582fbf5700909a35",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-09T16:16:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b6896f2d9af854275762e2c05d2be9d09db9a8be",
          "body": null,
          "is_bot": false,
          "headline": "feat: extend export command accept individual EXPRESS files, fixes #61",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-09T16:16:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "39d7901fd694b2e3fa9bf7ff2c1e3e9f1327dd94",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.1.23",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2025-10-06T11:39:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4167941975a48d81b996d7dc2c73e1fb9f7bca01",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-06T11:22:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25af5627c9f9935bfa603ca9f3dc4de3a1e18608",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-06T11:22:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "23f4844e132f0eb77bcc95dbcb5df1c1392b0b13",
          "body": null,
          "is_bot": false,
          "headline": "feat: add export command, fixes #6",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-06T11:22:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e177c5f84c0b064ec091f22f036c01a3a0cdfe6d",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.1.22",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2025-10-05T02:19:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a8199ac12a90ea74f8e9aa451b4624c4923f21b",
          "body": null,
          "is_bot": false,
          "headline": "feat: change from terminal-table to table_tennis gem",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-05T02:18:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "589506a1e47e7df2d5a6589e492e928314963ec9",
          "body": null,
          "is_bot": false,
          "headline": "Bump suma to 0.1.21",
          "author_name": "github-actions",
          "author_login": null,
          "committed_at": "2025-10-03T01:20:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a666c5647a82ac34abb197a07ddc981a90ddfb10",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-03T01:18:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "35c23dd74fbc9e59e366fbb217d202d8b01a759b",
          "body": null,
          "is_bot": false,
          "headline": "chore: update readme",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-03T01:18:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "131764575850aca1a16f0e89b8f3d3ec0ba18786",
          "body": null,
          "is_bot": false,
          "headline": "chore: update loading order and lutaml xml adapter",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-03T01:18:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "87a2f77d1742444121454a04bb4ce1b9c6d245c0",
          "body": null,
          "is_bot": false,
          "headline": "chore: rubocop",
          "author_name": "Ronald Tse",
          "author_login": "ronaldtse",
          "committed_at": "2025-10-03T01:18:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 1,
      "commits_last_year": 102,
      "latest_release_at": "2025-11-17T03:02:34Z",
      "latest_release_tag": "v0.2.0",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 16,
      "days_since_latest_release": 252,
      "mean_days_between_releases": null
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 75,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "suma",
          "exists": true,
          "license": "BSD-2-Clause",
          "keywords": [],
          "ecosystem": "rubygems",
          "matches_repo": true,
          "registry_url": "https://rubygems.org/gems/suma",
          "is_deprecated": false,
          "latest_version": "0.5.2",
          "repository_url": "https://github.com/metanorma/suma",
          "versions_count": 39,
          "total_downloads": 29667,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2024-06-07T03:53:03.063000Z",
          "latest_published_at": "2026-07-28T01:06:11.087000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 1,
      "watchers": 8,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 13
    },
    "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": 11805,
      "source_files_sampled": 101,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 8037
    },
    "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": 19,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "rubygems"
      ],
      "dependencies": [
        {
          "name": "canon",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "metanorma",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "nokogiri",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "openssl",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": "~> 3.0"
        },
        {
          "name": "rake",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rspec",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rubocop",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rubocop-performance",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rubocop-rake",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        },
        {
          "name": "rubocop-rspec",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "canon",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "metanorma",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "nokogiri",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "openssl",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rake",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rspec",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rubocop",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rubocop-performance",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rubocop-rake",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rubocop-rspec",
            "direct": true,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "expressir",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "glossarist",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "lutaml-model",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "plurimath",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "ruby-progressbar",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "rubyzip",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "svg_conform",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "table_tennis",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          },
          {
            "name": "thor",
            "direct": false,
            "version": null,
            "ecosystem": "rubygems"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 19,
        "direct_count": 10,
        "indirect_count": 9
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 3,
        "merged_prs": 54,
        "open_issues": 10,
        "closed_ratio": 0.778,
        "closed_issues": 35,
        "closed_unmerged_prs": 5
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "ronaldtse",
          "commits": 112,
          "avatar_url": "https://avatars.githubusercontent.com/u/11865?v=4"
        },
        {
          "type": "User",
          "login": "kwkwan",
          "commits": 42,
          "avatar_url": "https://avatars.githubusercontent.com/u/29566367?v=4"
        },
        {
          "type": "User",
          "login": "opoudjis",
          "commits": 38,
          "avatar_url": "https://avatars.githubusercontent.com/u/1911039?v=4"
        },
        {
          "type": "User",
          "login": "CAMOBAP",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/2169738?v=4"
        },
        {
          "type": "User",
          "login": "manuelfuenmayor",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/33627611?v=4"
        }
      ],
      "contributors_sampled": 5,
      "top_contributor_share": 0.569
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "rake.yml",
        "release.yml"
      ],
      "has_docs_dir": false,
      "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": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "8 out of 8 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/16 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 5 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 0,
            "reason": "license file not 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": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "222b291f5088c8c23031d0f3641f1fbea1b44569",
        "ran_at": "2026-07-28T01:11:39Z",
        "aggregate_score": 4.6,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-28T01:07:47Z",
      "oldest_open_prs": [
        {
          "number": 35,
          "created_at": "2025-04-04T14:07:42Z",
          "last_comment_at": "2026-07-02T13:45:25Z",
          "last_comment_author": "opoudjis"
        },
        {
          "number": 95,
          "created_at": "2026-07-02T13:44:16Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 108,
          "created_at": "2026-07-25T14:59:30Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-28T00:35:16Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": [
        {
          "number": 11,
          "created_at": "2024-09-20T05:52:13Z",
          "last_comment_at": "2024-09-20T14:46:18Z",
          "last_comment_author": "TRThurman"
        },
        {
          "number": 12,
          "created_at": "2024-10-08T11:20:44Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 36,
          "created_at": "2025-04-10T01:49:08Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 37,
          "created_at": "2025-04-10T04:16:37Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 63,
          "created_at": "2025-10-09T12:49:30Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 80,
          "created_at": "2026-01-08T06:12:20Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 85,
          "created_at": "2026-02-10T15:51:58Z",
          "last_comment_at": "2026-07-02T20:22:08Z",
          "last_comment_author": "stuartgalt"
        },
        {
          "number": 90,
          "created_at": "2026-05-26T18:50:29Z",
          "last_comment_at": "2026-06-23T14:19:42Z",
          "last_comment_author": "manuelfuenmayor"
        },
        {
          "number": 94,
          "created_at": "2026-06-30T15:51:13Z",
          "last_comment_at": "2026-07-07T10:31:46Z",
          "last_comment_author": "opoudjis"
        },
        {
          "number": 107,
          "created_at": "2026-07-23T13:10:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/metanorma/suma",
    "host": "github.com",
    "name": "suma",
    "owner": "metanorma"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 60,
      "inputs": {
        "security": 46,
        "vitality": 70,
        "community": 40,
        "governance": 66,
        "engineering": 70
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 70,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "commits_last_year": 102,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 16
            },
            "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": "16/52 weeks with commits",
                "points": 11.1,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 16
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "102 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 102
                    }
                  }
                ],
                "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": "moderate",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 62,
            "inputs": {
              "releases_count": 1,
              "latest_release_tag": "v0.2.0",
              "releases_from_tags": false,
              "days_since_latest_release": 252,
              "mean_days_between_releases": null
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "1 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 252 days ago",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 252
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "cadence unknown (single release)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "release_cadence_unknown",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 0,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 0 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "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": 40,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 5,
            "inputs": {
              "forks": 0,
              "stars": 1,
              "watchers": 8,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "1 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "8 watchers",
                "points": 4.7,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 8
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 67,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "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": "no license file detected",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "license_absent",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 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": 58,
            "inputs": {
              "packages": [
                "suma"
              ],
              "dependents": null,
              "ecosystems": "rubygems",
              "total_downloads": 29667,
              "monthly_downloads": null
            },
            "components": [
              {
                "key": "total_downloads",
                "name": "Total downloads",
                "detail": "29,667 downloads all-time across rubygems",
                "points": 46.5,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_total",
                    "params": {
                      "count": 29667,
                      "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": 66,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 36,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 5,
              "top_contributor_share": 0.569
            },
            "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 57% of commits",
                "points": 9.7,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 57
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "5 contributors",
                "points": 6.8,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 71,
            "inputs": {
              "merged_prs": 54,
              "open_issues": 10,
              "closed_issues": 35,
              "issue_closed_ratio": 0.778,
              "closed_unmerged_prs": 5
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "78% of issues closed",
                "points": 36.4,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 78
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "54/59 decided PRs merged",
                "points": 35,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 54,
                      "decided": 59
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/16 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": 69,
            "inputs": {
              "followers": 95,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "metanorma",
              "public_repos": 331,
              "account_age_days": 2993
            },
            "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": "95 followers of metanorma",
                "points": 14.3,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 95,
                      "login": "metanorma"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "331 public repos, account ~8 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 331
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 8
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "suma"
              ],
              "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": "39 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 39
                    }
                  }
                ],
                "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": 70,
        "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": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "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": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 46,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 46,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 4.6
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "8 out of 8 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/16 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file not detected",
                "points": 0,
                "status": "missed",
                "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 not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 3
            },
            "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": 55,
        "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.76,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 8037
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "76 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 76,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 33,
            "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": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "moderate",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "primary_language": "Ruby",
              "largest_source_bytes": 11805,
              "source_files_sampled": 101,
              "oversized_source_files": 0
            },
            "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": "0/101 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 101,
                      "oversized": 0
                    }
                  }
                ],
                "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-28T01:11:55.016478Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/m/metanorma/suma.svg",
  "full_name": "metanorma/suma",
  "license_state": "absent",
  "license_spdx": null
}

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.