原始 JSON 报告 机器可读
{
"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
}