Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-28 01:11 UTC

metanorma / suma

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

RubySin licencia detectada★ 1 estrella⑂ 0 forksdesde jun 2024Ver en GitHub ↗

metanorma/suma tiene un índice de salud de 60 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Vitality (70/100) y la más baja, Community & Adoption (40/100). Se actualizó por última vez hoy. Una sola persona concentra la mayor parte del trabajo reciente.

60
global / 100
Moderado

Índice de salud del software

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

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

Perfil de puntuación

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

Titularidad

MetanormaOrganización
95 seguidores331 repositorios públicosdesde may 2018

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

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
RubyGemssuma0.5.2-39hace 0 días

Métricas por categoría

Vitalidad

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

70Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
11.1/36Cadencia de commits — 16/52 semanas con commits
18/18Volumen de commits — 102 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year102
human_commit_share1
days_since_last_push0
active_weeks_last_year16
Cómo se puntúa
27/27Publica versiones — 1 versiones publicadas
16.2/36Recencia de las versiones — última versión hace 252 días
12.6/27Cadencia de publicación — cadencia desconocida (una sola versión)
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count1
latest_release_tagv0.2.0
releases_from_tagsno
days_since_latest_release252
mean_days_between_releases
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

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

40En riesgo · 18% del índice global
Cómo se puntúa
0/60Estrellas — 1 estrellas
0/25Forks — 0 forks
4.7/15Observadores — 8 observadores
Datos de entrada utilizados
forks0
stars1
watchers8
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
0/22.5Licencia — no se detectó ningún archivo de licencia
18/18Guía CONTRIBUTING
13.5/13.5Código de conducta
0/7.2Plantilla de issues
6.3/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_licenseno
has_contributing
has_issue_templateno
has_code_of_conduct
has_pull_request_template
Cómo se puntúa
46.5/80Descargas totales — 29.667 descargas históricas en rubygems
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packagessuma
dependents
ecosystemsrubygems
total_downloads29.667
monthly_downloads
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

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

66Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
9.7/22.5Distribución de commits — el principal contribuyente firma el 57% de los commits
6.8/13.5Amplitud de contribuyentes — 5 contribuyentes
10/10OpenSSF Scorecard: Contributors — project has 5 contributing companies or organizations
Datos de entrada utilizados
bus_factor1
contributors_sampled5
top_contributor_share0,569
Cómo se puntúa
36.4/46.8Resolución de issues — 78% de issues cerradas
35/38.3Aceptación de PR — 54/59 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/16 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs54
open_issues10
closed_issues35
issue_closed_ratio0,778
closed_unmerged_prs5
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
14.3/25Alcance del propietario — 95 seguidores de metanorma
25/25Trayectoria — 331 repos públicos, cuenta de ~8 años
Datos de entrada utilizados
followers95
owner_typeOrganization
is_verified
owner_loginmetanorma
public_repos331
account_age_days2993
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en rubygems
35/35Recencia de publicación — última publicación hace 0 días
20/20Historial de versiones — 39 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagessuma
ecosystemsrubygems
any_deprecatedno
min_days_since_publish0

Calidad de Ingeniería

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

70Bueno · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 2 flujo(s) de trabajo
24/24Pruebas presentes
16/16Configuración de linter — .rubocop.yml
0/9.6Hooks de pre-commit
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 8 out of 8 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_config
has_precommit_configno

Documentación

50Moderado
Cómo se puntúa
30/30README
0/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepage
has_readme
has_docs_dirno
has_description

Seguridad

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

46En riesgo · 16% del índice global
Cómo se puntúa
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.5Licencia — 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 — sin datos
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 — sin datos
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate4,6
Excluidos de la puntuación (sin datos o no aplicable): packaging, signed_releases. Los pesos restantes se han renormalizado.

Preparación para IA

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

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

Datos clave

1estrellas de GitHub
5contribuidores
102commits en los últimos 12 meses
0días desde el último push
1versiones publicadas
1factor bus
10issues abiertas
RubyGemsecosistemas de paquetes

Advertencias de recopilación de datos

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

Más detalle

OpenSSF Scorecard 4.6 / 10
4.6agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).Scorecard v5.5.0 · 2026-07-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
n/dPackagingpackaging 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
n/dSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
Dependencias directas 10
RegistroPaqueteRestricción de versiónManifiesto
RubyGemscanonGemfile
RubyGemsmetanormaGemfile
RubyGemsnokogiriGemfile
RubyGemsopenssl~> 3.0Gemfile
RubyGemsrakeGemfile
RubyGemsrspecGemfile
RubyGemsrubocopGemfile
RubyGemsrubocop-performanceGemfile
RubyGemsrubocop-rakeGemfile
RubyGemsrubocop-rspecGemfile
Todas las dependencias 19

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

RegistroPaqueteVersiónRelación
RubyGemscanondirecta
RubyGemsmetanormadirecta
RubyGemsnokogiridirecta
RubyGemsopenssldirecta
RubyGemsrakedirecta
RubyGemsrspecdirecta
RubyGemsrubocopdirecta
RubyGemsrubocop-performancedirecta
RubyGemsrubocop-rakedirecta
RubyGemsrubocop-rspecdirecta
RubyGemsexpressirindirecta
RubyGemsglossaristindirecta
RubyGemslutaml-modelindirecta
RubyGemsplurimathindirecta
RubyGemsruby-progressbarindirecta
RubyGemsrubyzipindirecta
RubyGemssvg_conformindirecta
RubyGemstable_tennisindirecta
RubyGemsthorindirecta
Avisos de dependencias sin evaluar

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

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [],
      "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
}

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

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

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