Raw JSON report machine-readable
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 575,
"has_wiki": true,
"homepage": null,
"languages": {
"Ruby": 258536,
"Shell": 131
},
"pushed_at": "2026-07-13T21:04:12Z",
"created_at": "2010-10-03T05:18:16Z",
"owner_type": "User",
"updated_at": "2026-07-13T21:04:49Z",
"description": "A generic swappable back-end for XML parsing",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "Ruby",
"significant_languages": [
"Ruby"
]
},
"owner": {
"blog": null,
"name": "Erik Berlin",
"type": "User",
"login": "sferik",
"company": null,
"location": "San Francisco",
"followers": 2649,
"avatar_url": "https://avatars.githubusercontent.com/u/10308?v=4",
"created_at": "2008-05-14T20:36:12Z",
"is_verified": null,
"public_repos": 216,
"account_age_days": 6642
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v0.9.1",
"kind": "patch",
"published_at": "2026-05-04T18:32:52Z"
}
],
"recent_commits": [
{
"oid": "391efee2f509a7afde833eee8315f0ec7f59f16b",
"body": "With the benchmark defaults of 0.03s warmup and 0.15s samples, the\nJIT engines are measured cold and close parser pairs flip: on\nTruffleRuby, nokogiri outranked oga by 21% in CI, while a warmed-up\nrun keeps the coded order (rexml, oga, nokogiri) within tolerance.\nGive the verify_preference job two seconds of warmup and one-second\nmeasurement windows so Graal and the JVM compile the hot paths\nbefore the ranking is asserted.",
"is_bot": false,
"headline": "Warm up the JIT before verifying parser preference order",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-07-13T20:48:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "54aacd371ddc7fe7bd5f6dec99724421a900b0b9",
"body": "rdoc 8 depends on rbs 4, whose native extension cannot build on\nJRuby, and mutant pulls rdoc in via irb, so the existing platform\ngates on rbs and steep were bypassed; rdoc 7 has no rbs dependency.\nSkip the lowercase-require-path test on JRuby, where require-site\ncaching keeps warm call sites bound to the original Kernel#require\nso the stub never sees the call.",
"is_bot": false,
"headline": "Fix JRuby CI: cap rdoc below 8 and skip a require-stubbing test",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-07-13T11:46:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fd5955e32926847d96850b8d19525b01f7597047",
"body": null,
"is_bot": false,
"headline": "Remove the redundant `keyword_init: true`",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-07-13T11:12:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c4ed4e7f22ef05acfc49df2d5bb540df64aa5e18",
"body": "Collapse the 11 reopenings of MultiXMLBenchmark in benchmark.rb into\na single class body and extract the deprecated MultiXml constant shim\nfrom lib/multi_xml.rb into lib/multi_xml/legacy_constant.rb, required\nafter multi_xml/deprecated so the forwarder snapshot still sees the\ncomplete public API.",
"is_bot": false,
"headline": "Fix Style/OneClassPerFile offenses",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-07-13T11:10:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "046d7687e90a81f42cb9dbd86740401d1fd28563",
"body": null,
"is_bot": false,
"headline": "Use to_h { ... } instead of each_with_object",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-07-13T04:29:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9acf8036f1d82ec74169c596dd1da7499c901b0e",
"body": null,
"is_bot": false,
"headline": "Update SimpleCov to version 1.0",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-07-13T04:24:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "52a03525397b1b0b1a3bd49ec7bee09fdd7154c9",
"body": null,
"is_bot": false,
"headline": "Bump version to 0.9.1",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-05-04T17:36:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1c34a5c51c32ec3a41bc6c232f8ee7a5d96463c0",
"body": "Mirror multi_json's push.yml: after the gem is published to RubyGems,\ncreate a GitHub release for the tag with auto-generated notes. The\n`gh release view` check makes the step idempotent in case the workflow\nre-runs against an existing tag.",
"is_bot": false,
"headline": "Create a GitHub release on tag push",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-05-04T17:36:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "533d505f49cdd09c831a7d81270127714bfa77c2",
"body": "The legacy MultiXml constant forwarded calls to MultiXML via\nmethod_missing, but Module#method doesn't consult method_missing, so\nMultiXml.method(:load) resolved to the inherited Kernel#load and\ncrashed with LoadError when invoked. Any caller capturing the legacy\nconstant's load method as a Method o\n[…]\nevery public method\nMultiXML exposes, so Module#method finds the forwarder directly. Drop\nthe now-dead method_missing and respond_to_missing? hooks; the eager\nforwarders cover the full public surface.",
"is_bot": false,
"headline": "Fix MultiXml.method(:load) resolving to Kernel#load",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-05-04T17:23:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f785ca1898ac0e9cb293b433dbffdf990e2021d3",
"body": null,
"is_bot": false,
"headline": "Bump version to 0.9.0",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-05-02T16:39:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9164cc4bc566214ff6a4f3c5bbe80948b9d1f550",
"body": "Three OxNamespaceTest collision tests fail intermittently on TruffleRuby\nwhen run in the full suite. The handler hash ends up empty\n(`{\"root\" => {}}`) which post-typecast collapses to `{\"root\" => nil}`,\nbreaking the assertion.\n\nRoot cause is TruffleRuby's JIT, not Ox: when earlier tests in the\nproce\n[…]\n_handling_test.rb to match the existing\nskip in parser_integration_test.rb, and filter `lib/multi_xml/parsers/ox.rb`\nfrom coverage on TruffleRuby so the missing lines don't trip the\nSimpleCov minimum.",
"is_bot": false,
"headline": "Skip Ox tests on TruffleRuby",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-05-02T16:39:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d4887e322b9f7fadf26ad8fed0630180b8aa2d44",
"body": "The previous table reported absolute throughput numbers from a\nsingle MRI run, which went stale on every benchmark refresh and\ntold readers nothing about JRuby or TruffleRuby. The new table\nshows the actual PARSER_PREFERENCE ordering on each supported\nruntime, surfacing the TruffleRuby flip (rexml ahead of oga,\nnokogiri last) that the engine-specific constant encodes. CI\nkeeps it honest by failing if the observed ranking diverges.",
"is_bot": false,
"headline": "Replace benchmark scores in README with per-engine preference table",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-30T17:58:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "af45aad809b6b088878de9ee88c8959a4672d7d3",
"body": "Adjacent parsers in PARSER_PREFERENCE whose observed throughput is\nwithin 10% of each other are now treated as tied, so a noisy run\nthat flips a close pair (oga vs nokogiri on TruffleRuby is 4% apart)\nno longer fails the check. Real ordering bugs -- e.g. preferring\nrexml over oga on MRI, where the g\n[…]\n Pairwise tolerance check on adjacent\npositions catches transitive violations too: if A > B > C in\npreference but actual scores have C significantly above A, the\nadjacent A-B or B-C check picks it up.",
"is_bot": false,
"headline": "Tolerate noise in PARSER_PREFERENCE verifier",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-30T17:37:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d6f805eabb3ca0550642292aa6368502e8d0da15",
"body": "TruffleRuby's JIT inverts the FFI-vs-pure-Ruby tradeoff: rexml jumps\nto the head of auto-detection (after ox, which is filtered out by\nskip_on_platform?) and nokogiri falls to last. Pin a TruffleRuby\nordering of rexml > libxml > oga > nokogiri behind a RUBY_ENGINE\ncheck so the verifier passes on all\n[…]\nocov:) wrap the conditional because the\nunreachable branch on a given engine would otherwise drop branch\ncoverage below the 100% MRI threshold.\n\nAlso adds truffleruby to the benchmark workflow matrix.",
"is_bot": false,
"headline": "Add TruffleRuby-specific PARSER_PREFERENCE",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-30T17:37:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "41430029f529cd8c0d50539614ce9ae2f466f57e",
"body": "Adds jruby-10.0 to the benchmark workflow matrix. JRuby's available\nparser set (no ox/libxml; oga crashes on JRuby 10) shrinks the\nfiltered comparison to nokogiri vs rexml, which still matches\nPARSER_PREFERENCE -- so a single shared constant works for both\nruntimes.",
"is_bot": false,
"headline": "Verify PARSER_PREFERENCE on JRuby in addition to MRI",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-30T16:22:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d77088470f9822e503e7e2e7fa60740e95c9c89b",
"body": "Adds a --verify-preference flag to benchmark.rb and a CI workflow\nthat runs the benchmark and asserts the throughput ranking, filtered\nto parsers in MultiXML::PARSER_PREFERENCE, matches the constant's\norder. Missing parsers (e.g. ox unavailable on JRuby) are tolerated.\nThe check pins to ubuntu-latest + Ruby 4.0 since benchmark numbers\naren't comparable across runtimes.",
"is_bot": false,
"headline": "Verify PARSER_PREFERENCE matches benchmark ranking in CI",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-30T16:20:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "182fa34e5b7635c5cfac07e45b1ee7e99da190b2",
"body": "Swap oga ahead of rexml so the constant's \"fastest first\" promise is\nhonest: oga (0.168) outperforms rexml (0.117) on the bundled\nbenchmark suite. Affects auto-detection only when none of ox,\nlibxml-ruby, or nokogiri are installed; explicit parser selection\nis unchanged.",
"is_bot": false,
"headline": "Reorder PARSER_PREFERENCE to match benchmark throughput",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-30T16:20:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8b1c84bb317c26cf573f30ec1a597b5058dd878b",
"body": "Re-ran the suite on Ruby 4.0 / Apple Silicon. libxml edges past\nnokogiri_sax for the #2 slot; other relative positions unchanged.\nAlso drops the \":parsers\" namespace from the rake invocation to\nmatch the renamed task.",
"is_bot": false,
"headline": "Refresh benchmark ranking table in README",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-30T16:20:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9c0e7e1c294853120f6dd4c0551bd2daf609f7aa",
"body": "Drops the namespace and the alias since there's only one benchmark\ntask. Invocation simplifies to \"rake benchmark\"; BENCHMARK_ARGS still\nforwards to benchmark.rb.",
"is_bot": false,
"headline": "Promote benchmark:parsers to a top-level rake benchmark task",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-30T16:06:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b4c127d42f7ccdb4ea747014f34dc5874134cb4f",
"body": "Oga's Java backend crashes on JRuby 10 with java.lang.NoSuchMethodError,\nwhich extends java.lang.Error and bypasses StandardError rescues --\naborting the whole benchmark instead of letting the parser get excluded.\n\nCatch Java::JavaLang::Throwable alongside StandardError on JRuby so the\nexisting excluded-parsers path handles backend incompatibilities the\nsame way it handles output mismatches and Ruby exceptions.",
"is_bot": false,
"headline": "Skip JRuby-incompatible parsers in benchmark validation",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-30T16:01:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fe000beffa239b20e0e8ab982c706adca67ccc13",
"body": null,
"is_bot": false,
"headline": "Add regression test for mixed-content inline text",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-29T01:18:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6e14d5bb7cd25f9d01915b498a58c2795308d4cf",
"body": null,
"is_bot": false,
"headline": "Add parser benchmark and document benchmark ranking",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-29T01:18:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "15265c39ebc5d790ffbd36816f78fdb95fdb9057",
"body": null,
"is_bot": false,
"headline": "Fix Ox mixed-content text aggregation in SAX parser",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-29T01:18:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9343839f5464ff5771cd760be02c7dc7e68f1dfb",
"body": "Add a shared Parser mixin that reads the ParseError constant off the\nextending module via const_get with inherit: false (so stray top-level\n::ParseError doesn't leak through). Every built-in parser extends it\nand declares its backend exception class as ParseError, matching the\nMultiJSON::Adapter convention.\n\nCustom parsers can either extend Parser + define a ParseError constant\nor keep defining a .parse_error method directly; validate_parser!\naccepts both styles.",
"is_bot": false,
"headline": "Introduce MultiXML::Parser base module with ParseError constant",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-29T01:18:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bc34f7e2ac5b0160b23f34d293489a415aafb1be",
"body": "Raised when the parser spec is invalid, requiring the parser file\nraises LoadError, or the resolved parser doesn't satisfy the contract\n(must respond to .parse and define either a ParseError constant or a\n.parse_error method). Inherits from ArgumentError and carries the\noriginal exception's class name in its message, matching the role of\nMultiJSON::AdapterError.",
"is_bot": false,
"headline": "Add MultiXML::ParserLoadError for parser selection failures",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-29T01:18:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ba338d40718d79e06c2b28b817b82361eeec16a6",
"body": "Introduce process-wide default options that merge between DEFAULT_OPTIONS\nand call-site overrides. Accepts a Hash or a callable (Proc/lambda); a\ncallable receives the call-site hash as its sole positional argument so\ndefaults can be computed per-call. Matches MultiJSON.parse_options.",
"is_bot": false,
"headline": "Add MultiXML.parse_options / .parse_options= for global defaults",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-29T01:18:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e76301065c24699a656e37d541f9008e64fea4c4",
"body": "The override lives in Fiber[:multi_xml_parser] so concurrent fibers\nand threads each see their own parser without racing on a shared\nmodule variable; nested calls save and restore the previous\nfiber-local value. Matches MultiJSON.with_adapter.",
"is_bot": false,
"headline": "Add MultiXML.with_parser for fiber-local scoped overrides",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-29T01:18:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a5c53bbdb46eef4e37b48cd1156c3a413c62478f",
"body": "Add JRuby 10.0 and TruffleRuby 33.0 (native and JVM) to the CI matrix,\nmatching the test coverage of MultiJSON. TruffleRuby is\nexcluded from Windows runners since the setup-ruby action doesn't\nsupport it there.",
"is_bot": false,
"headline": "Test against JRuby and TruffleRuby",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-29T01:18:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5aa5fcbe80290935d05921c2c34dff0bbf2e3fb5",
"body": "Match Ruby stdlib's JSON.parse and MultiJSON. The\nlegacy :symbolize_keys option continues to work and emits a one-time\ndeprecation warning; it will be removed in 1.0. When both names appear\ntogether, :symbolize_names wins and :symbolize_keys is silently dropped.",
"is_bot": false,
"headline": "Rename :symbolize_keys option to :symbolize_names",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T20:06:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ce00fa7bb4581ef1b8048e605c32c9c2a822a2df",
"body": "Adopt the MultiJSON README layout: CI badges, intro paragraph, minimal\nusage example, error-handling block, deprecation table for 0.9.0, and\ncustom-parser section. Drop the \"Drop-in replacement for stdlib\" and\n\"Gem Variants\" sections since neither applies to MultiXML.",
"is_bot": false,
"headline": "Restructure README to match MultiJSON",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T20:06:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "da358245bfbd3957a7e9466ecc648b0f6f5cf0cf",
"body": "Match the MultiJSON.load → MultiJSON.parse convention. MultiXML.load\ncontinues to work and emits a one-time deprecation warning; it will\nbe removed in 1.0.",
"is_bot": false,
"headline": "Add a deprecated load alias for parse",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T20:06:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9099c3336a703ab942ee356a8f1a0456003fb50f",
"body": "Use the all-caps acronym matching sister library MultiJSON. The legacy\nMultiXml constant continues to resolve via method_missing and\nconst_missing with a one-time deprecation warning, so every existing\ncall site keeps working through the 0.x line.",
"is_bot": false,
"headline": "Rename MultiXml to MultiXML and deprecate MultiXml",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T18:05:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2dee313b83db33b071cd4eb21585a7f5793a8bd7",
"body": "When attributes with different namespace prefixes strip to the same\nlocal name (e.g. `foo:id` and `bar:id` both become `id`), collect their\nvalues in an array while preserving document order and keeping attribute\nvalues ahead of any colliding child elements. The libxml SAX parser\nfalls back to the DOM backend in this case since its callback drops\nprefixes from attribute qnames.",
"is_bot": false,
"headline": "Handle namespaced attribute name collisions consistently",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T18:04:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f0eab96d04f223bf17b21443ec033dcd760a8b1b",
"body": null,
"is_bot": false,
"headline": "Fix parser detection",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T18:04:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ae0e9d109287cc7e62c140985305399fadcc9579",
"body": null,
"is_bot": false,
"headline": "Harden namespace parsing and extract parse helpers",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T18:04:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9c1313ea794518831253ec33e320c403f352715b",
"body": "Add a :namespaces option to MultiXml.parse that makes every backend\nproduce byte-identical output:\n\n* :strip (default) — drop xmlns declarations and prefixes, matching\n today's libxml/nokogiri behavior\n* :preserve — keep source prefixes (\"atom:rel\") and xmlns decls",
"is_bot": false,
"headline": "Fix inconsistent namespace handling across parsers",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T18:04:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1d930a0fe3545b342e934764e168a19c3349118f",
"body": null,
"is_bot": false,
"headline": "Ignore .mutant directory",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T18:04:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "27fd3bb59f79a0f746256afa041d03b890fa14a6",
"body": "libxml-ruby 6.0.0 removed the deprecated `libxml.rb` shim, so\n`require \"libxml\"` now raises LoadError. Switch to the canonical\n`require \"libxml-ruby\"`, which is present in both 5.x and 6.x.\n\nAlso bump steep to >= 2 so CI resolves against rbs 4.x.",
"is_bot": false,
"headline": "Support libxml-ruby 6.0.0",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T18:04:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "11dba85e7d051623d770915a61f25927abd93a3f",
"body": "```\nFinished in 0.050951s, 12600.3415 runs/s, 18586.4851 assertions/s.\n\n 1) Error:\nLoadParserCamelizeTest#test_load_parser_handles_underscore_names:\nLoadError: cannot load such file -- libxml\n /Users/sue445/.rbenv/versions/4.0.2/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'\n /Users/su\n[…]\n_xml.rb:110:in 'MultiXml.load_parser'\n test/load_parser_test.rb:56:in 'LoadParserCamelizeTest#test_load_parser_handles_underscore_names'\n\n642 runs, 947 assertions, 0 failures, 1 errors, 0 skips\n```",
"is_bot": false,
"headline": "Fix error with libxml-ruby 6.0.0",
"author_name": "sue445",
"author_login": "sue445",
"committed_at": "2026-04-28T18:04:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "32d0dc255b22bbfb4318d02699950181490ca552",
"body": "…ith rbs v4\n\n```\nlib/multi_xml/errors.rb:1:0: [error] Type checking failed due to error in library RBS file\n│ Different superclasses are specified for `::Psych::SyntaxError`\n│ (/Users/sue445/workspace/github.com/sferik/multi_xml/vendor/bundle/ruby/4.0.0/gems/rbs-4.0.2/stdlib/psych/0/psych.rbs:434:2)\n│\n│ Diagnostic ID: Ruby::LibraryRBSError\n│\n└ module MultiXml\n ~~~~~~~~~~~~~~~\n```",
"is_bot": false,
"headline": "Fix Different superclasses are specified for `::Psych::SyntaxError` w…",
"author_name": "sue445",
"author_login": "sue445",
"committed_at": "2026-04-28T18:04:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c4aee68fe0a7b55950033302fb7ca2a643dca99f",
"body": null,
"is_bot": false,
"headline": "Test on Ruby 4.0",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-04-28T18:04:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c016f910f3fb35dcb050d7a5393b1773bae44bc0",
"body": null,
"is_bot": false,
"headline": "Bump version to 0.8.1",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-01-08T14:39:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7c8977fb78590930359fae0e5082a821aa342d06",
"body": "Closes https://github.com/sferik/multi_xml/issues/73.",
"is_bot": false,
"headline": "Fix array unwrapping when elements contain nil",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-01-08T06:38:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "75ea04280c5f4294a0e409fef5d3c3767148234e",
"body": null,
"is_bot": false,
"headline": "Update to Minitest 6",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2026-01-06T04:26:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "df3bcded2db18c5d2eb961c393860f7ab02f07a6",
"body": null,
"is_bot": false,
"headline": "Bump version to 0.8.0",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T14:09:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1d87b8f0e2dfa4d08276b671ef68b13aa5c8f71d",
"body": null,
"is_bot": false,
"headline": "Add push workflow and update release rake task",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T14:09:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cea6be3e3770dccab173d305bfacb97ed9050717",
"body": null,
"is_bot": false,
"headline": "Document Ruby 4 support",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0a3bd225648181a32cdef85a75459de3ecbc761c",
"body": null,
"is_bot": false,
"headline": "Refactor",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f5d3655f6d944968256ef4280f1b1a2d0286a2a6",
"body": null,
"is_bot": false,
"headline": "Remove test skips",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e43f18848d90fe79fe4a33ad2eac94764ef0c2af",
"body": null,
"is_bot": false,
"headline": "Increase branch coverage to 100%",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6811d856c0e30258b7290d8f0eb5c2fefeee34da",
"body": null,
"is_bot": false,
"headline": "Fix tests on Windows",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "eaa386cfef4ebb679e78118cb17f2ffb26a7d258",
"body": null,
"is_bot": false,
"headline": "Drop support for JRuby",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "eaaff8b9b5452598b6421f4d654e14d090b40c7f",
"body": null,
"is_bot": false,
"headline": "Add type checking with RBS and Steep",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "49702d92a9ebc8e6584e5d24833c1d9ecd671268",
"body": null,
"is_bot": false,
"headline": "More refactoring",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2a0ff51f426079b0a1baac363efa437baca1bf13",
"body": null,
"is_bot": false,
"headline": "More test cleanup",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2cca440fc13daa0255af0f5743ed57973888e834",
"body": null,
"is_bot": false,
"headline": "Kill remaining mutants",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "61ef966dde3808ccbecbbca27e2d676f7a061e5d",
"body": null,
"is_bot": false,
"headline": "Cleanup tests",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "be8df358efea132db3f1cc18518251e535c9c181",
"body": null,
"is_bot": false,
"headline": "Kill mutants",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "18144f88b1bf1a2d639bdf2450d7397ce5ce45cb",
"body": null,
"is_bot": false,
"headline": "Suppress oga warnings",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "661b419703cfe50b3d7f63431c91b6cacbab3a0d",
"body": null,
"is_bot": false,
"headline": "Add mutant",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9fe7948112879b3d449be2bca2ef4194b73f09cd",
"body": null,
"is_bot": false,
"headline": "100% c0 code coverage",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c58286849951cd2f6cac2d9b19d43104e165a520",
"body": null,
"is_bot": false,
"headline": "Covert from RSpec to Minitest",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "885ff010de9a46218d93ce378e896268b208d0a9",
"body": null,
"is_bot": false,
"headline": "100% documentation coverage",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "78a715f7232496ecbefde5ced529fadfc4a508e8",
"body": null,
"is_bot": false,
"headline": "More refactoring",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5ac2c349a59651872bbcf4ae3a4d9b03fff5c06c",
"body": null,
"is_bot": false,
"headline": "Extract modules and constants into separate files",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "156fc5c0b9be47285dca8084fc6bc3a7c2e5d75b",
"body": null,
"is_bot": false,
"headline": "Update workflows",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2a78cb3f451851a9d78ddfa03ea2bf3834028ca8",
"body": null,
"is_bot": false,
"headline": "Extract global variables into SpeedTest module",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "81c4fd8f3dbb1d2becdc328a3f862c64fde23b18",
"body": null,
"is_bot": false,
"headline": "Replace @xml instance variables with let(:xml) declarations",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c3fadd0acaf28939e59b08285fbb7213564cd824",
"body": null,
"is_bot": false,
"headline": "Refactor",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6127e278a879391a247573cdd4abb4855421e26c",
"body": null,
"is_bot": false,
"headline": "Refactor code into Helpers module",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e0530a935ad1677792ff1348c8faf6b3a73ca429",
"body": null,
"is_bot": false,
"headline": "rake standard:fix",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "695729f7103305ed852da1efbb493504d5db773c",
"body": "Resolves https://github.com/sferik/multi_xml/issues/32.",
"is_bot": false,
"headline": "Make parsing errors inspectable with cause and xml accessors",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ade3c5005ae76c4ca835186c25dac9c3a580e481",
"body": "Previously, parsers handled whitespace-only content differently:\n - nokogiri, libxml, oga: always stripped whitespace\n - ox, rexml: always preserved whitespace\n\nNow all parsers have the same behavior:\n - Empty elements return nil\n - Whitespace-only content with no children/attributes is preserve\n[…]\n>\" -> {\"tag\" => \" \"}\n \"<tag> <child/></tag>\" -> {\"tag\" => {\"child\" => nil}}\n \"<tag attr='x'> </tag>\" -> {\"tag\" => {\"attr\" => \"x\"}}\n\nResolves https://github.com/sferik/multi_xml/issues/46.",
"is_bot": false,
"headline": "Fix inconsistent whitespace handling across parsers",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "663ac9d3325146ca5306c5db1ff4d33ac55d65e8",
"body": "Use top-level constant references (::Ox, ::LibXML, etc.) in the\n`defined?` checks to ensure we check for the actual gem constants rather\nthan the local parser module constants.\n\nPreviously, `defined?(Ox)` inside `MultiXml::Parsers::Ox` would find the\nparser module itself due to Ruby's constant looku\n[…]\nn't loaded. This\nresulted in \"undefined method `sax_parse' for Ox:Module\" errors in\nmultithreaded environments or when the gem wasn't preloaded.\n\nResolve https://github.com/sferik/multi_xml/issues/53.",
"is_bot": false,
"headline": "Fix constant lookup in parser require guards",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5dc70562a003eb7f621eeb46770090ec8255a3ed",
"body": "Implement experimental event-driven SAX parsing alternatives to the\nexisting DOM-based parsers. SAX parsing can be more memory-efficient for\nlarge XML documents since it doesn't build the entire DOM tree in memory.\n\nUsage:\n MultiXml.parser = :nokogiri_sax # Uses Nokogiri::XML::SAX::Parser\n Mu\n[…]\nracter references that\n SAX parsers return differently than DOM parsers\n - Both parsers properly raise MultiXml::ParseError for invalid XML\n\nResolves https://github.com/sferik/multi_xml/issues/10.",
"is_bot": false,
"headline": "Add SAX parsers for Nokogiri and LibXML",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c7f532af83963beb0204fcc5a4419cb1fdcbbe82",
"body": null,
"is_bot": false,
"headline": "Change bigdecimal dependency to >= 3.1, < 5",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-24T13:10:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f5929bd870a94c7b9ee7cb99d4cfd33d87ca05a7",
"body": "This reverts commit ecc425a26b5c2108732dfbf7d68e82cd7e16aec9.",
"is_bot": false,
"headline": "Revert \"Pass symbol as an argument to proc instead of a block\"",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-20T16:22:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c94bbfa4722f0356c111cc313baa8449817c31ae",
"body": "Allow specifying a parser for individual parse operations via the\n:parser option, enabling use of different parsers in the same\napplication without changing the class-level setting.\n\nThe option accepts symbols, strings, or parser modules, consistent with\nthe existing MultiXml.parser= API.\n\nResolves https://github.com/sferik/multi_xml/issues/63.",
"is_bot": false,
"headline": "Add per-parse :parser option to MultiXml.parse",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-20T07:32:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ecc425a26b5c2108732dfbf7d68e82cd7e16aec9",
"body": null,
"is_bot": false,
"headline": "Pass symbol as an argument to proc instead of a block",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-20T06:37:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8beccc67a578e2fc6ee269bbf464f425621ba9de",
"body": "Resolves https://github.com/sferik/multi_xml/issues/72.",
"is_bot": false,
"headline": "Update bigdecimal depdnency to ~> 4.0",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-12-20T06:36:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "338107755fab44ef425225a03d5bc2b0640e436d",
"body": null,
"is_bot": false,
"headline": "Bump version to 0.7.2",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-04-30T18:30:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "120fef648e702b903109eb001ef78c22585da616",
"body": null,
"is_bot": false,
"headline": "Update CI workflow",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-04-29T20:57:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7946028f70d4b41bfc967e3fdf3ec0e8f882ba7e",
"body": null,
"is_bot": false,
"headline": "Update LICENSE and README",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-04-29T20:03:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "00b3fca87f1eaa2cb3caefa1553684203278679d",
"body": null,
"is_bot": false,
"headline": "Add metadata hash",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-04-29T20:03:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f7708e14c9e8fda165d5172d110d2c2e708520ea",
"body": null,
"is_bot": false,
"headline": "Drop support for Ruby 3.1",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-04-29T19:40:36Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "70dab39a5597a2ff5bd535b0c30b0ce892cf9db3",
"body": null,
"is_bot": false,
"headline": "Use add_dependency instead of add_runtime_dependency",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-04-29T19:37:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4951afefae166bfbff2a35fd276abbfc41eeb693",
"body": null,
"is_bot": false,
"headline": "Specify plugins instead of require",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2025-04-29T19:32:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "854e26c603972ecf9898b99e7092a69fe619d6c9",
"body": null,
"is_bot": false,
"headline": "Bump version to 0.7.1",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-05-01T18:50:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d81665f1ce7cd1cad07cfab3f19a679c4fdad002",
"body": "…n stable\n\nSee discussion at https://github.com/sferik/multi_xml/commit/712cf97da3e6385179214644452cb7775d14e7d8#r141554010.",
"is_bot": false,
"headline": "Relax required Ruby version constraint to allow installation on Debia…",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-05-01T18:49:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1a2cde755452773aced4a870ff963a181a14381a",
"body": null,
"is_bot": false,
"headline": "Bump version to 0.7.0",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T19:08:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2b7e1637f800014bb7eaee6ed7dbffb5e08fa938",
"body": null,
"is_bot": false,
"headline": "Add bin for development",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T19:00:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "712cf97da3e6385179214644452cb7775d14e7d8",
"body": null,
"is_bot": false,
"headline": "Drop support for Ruby 3.0",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T18:59:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a2be7ce1ca13eb4b37d8ac88f6cbb893f18eccd2",
"body": null,
"is_bot": false,
"headline": "Update runtime dependency in gemspec",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T18:59:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "86fdc12fa4a4e2a588abb768589703fe6e7e2f38",
"body": null,
"is_bot": false,
"headline": "Update development dependencies in Gemfile",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T18:59:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1659443ea2659e7539e8bca2797dc3670e065985",
"body": null,
"is_bot": false,
"headline": "Clean up code",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T18:59:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0b832249e270db9cd957d1a2e7c978400f4db960",
"body": null,
"is_bot": false,
"headline": "Update copyright year",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T18:59:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b79adf03a93a4bb7cead2ab0752f54addad9c5df",
"body": null,
"is_bot": false,
"headline": "Update name",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T18:59:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d7ea5225f3e10c2aeb95e6d24235c6de1487cff2",
"body": null,
"is_bot": false,
"headline": "Clean up code",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T18:37:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f2ea10a7acedc044398d3ad11586b87dfb54d1ad",
"body": null,
"is_bot": false,
"headline": "Use parentheses for super with arguments",
"author_name": "Erik Berlin",
"author_login": "sferik",
"committed_at": "2024-04-30T18:33:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "54ff3221d241819d0183985494ef63126319f407",
"body": null,
"is_bot": false,
"headline": "Add ruby 3.3 to CI",
"author_name": "Earlopain",
"author_login": "Earlopain",
"committed_at": "2024-04-30T18:29:02Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 1,
"commits_last_year": 80,
"latest_release_at": "2026-05-04T18:32:52Z",
"latest_release_tag": "v0.9.1",
"releases_from_tags": false,
"days_since_last_push": 8,
"active_weeks_last_year": 9,
"days_since_latest_release": 78,
"mean_days_between_releases": null
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": true,
"health_percentage": 57,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "multi_xml",
"exists": true,
"license": "MIT",
"keywords": [],
"ecosystem": "rubygems",
"matches_repo": true,
"registry_url": "https://rubygems.org/gems/multi_xml",
"is_deprecated": false,
"latest_version": "0.9.1",
"repository_url": "https://github.com/sferik/multi_xml",
"versions_count": 29,
"total_downloads": 583709139,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": "2010-10-03T05:57:04.117000Z",
"latest_published_at": "2026-05-04T18:32:12.994000Z",
"latest_version_yanked": null,
"days_since_latest_publish": 78
}
]
},
"popularity": {
"forks": 38,
"stars": 172,
"watchers": 4,
"fork_history": {
"days": [
{
"date": "2010-10-04",
"count": 1
},
{
"date": "2011-06-05",
"count": 1
},
{
"date": "2011-08-24",
"count": 1
},
{
"date": "2011-12-30",
"count": 1
},
{
"date": "2012-04-16",
"count": 1
},
{
"date": "2012-05-08",
"count": 1
},
{
"date": "2013-01-11",
"count": 1
},
{
"date": "2013-05-31",
"count": 1
},
{
"date": "2013-07-02",
"count": 1
},
{
"date": "2013-07-08",
"count": 1
},
{
"date": "2013-07-12",
"count": 1
},
{
"date": "2013-08-14",
"count": 1
},
{
"date": "2013-09-02",
"count": 1
},
{
"date": "2013-12-27",
"count": 1
},
{
"date": "2014-02-10",
"count": 1
},
{
"date": "2015-02-10",
"count": 1
},
{
"date": "2015-02-14",
"count": 1
},
{
"date": "2015-06-18",
"count": 1
},
{
"date": "2015-10-16",
"count": 1
},
{
"date": "2015-11-02",
"count": 1
},
{
"date": "2016-03-24",
"count": 1
},
{
"date": "2016-07-24",
"count": 1
},
{
"date": "2016-12-05",
"count": 1
},
{
"date": "2017-04-06",
"count": 1
},
{
"date": "2017-05-18",
"count": 1
},
{
"date": "2017-06-22",
"count": 1
},
{
"date": "2019-02-01",
"count": 1
},
{
"date": "2019-03-04",
"count": 1
},
{
"date": "2020-07-28",
"count": 1
},
{
"date": "2021-01-12",
"count": 1
},
{
"date": "2022-02-12",
"count": 1
},
{
"date": "2023-06-02",
"count": 1
},
{
"date": "2024-01-02",
"count": 1
},
{
"date": "2024-02-13",
"count": 1
},
{
"date": "2024-05-11",
"count": 1
},
{
"date": "2024-06-09",
"count": 1
},
{
"date": "2026-04-17",
"count": 1
}
],
"complete": true,
"collected": 37,
"total_forks": 38
},
"star_history": {
"days": [
{
"date": "2010-10-03",
"count": 52
},
{
"date": "2010-10-05",
"count": 2
},
{
"date": "2011-03-10",
"count": 1
},
{
"date": "2011-06-13",
"count": 1
},
{
"date": "2011-06-20",
"count": 1
},
{
"date": "2011-06-29",
"count": 1
},
{
"date": "2013-02-20",
"count": 1
},
{
"date": "2013-03-07",
"count": 1
},
{
"date": "2013-03-09",
"count": 1
},
{
"date": "2013-04-18",
"count": 1
},
{
"date": "2013-04-20",
"count": 1
},
{
"date": "2013-04-22",
"count": 1
},
{
"date": "2013-06-10",
"count": 1
},
{
"date": "2013-06-17",
"count": 1
},
{
"date": "2013-06-27",
"count": 1
},
{
"date": "2013-07-04",
"count": 1
},
{
"date": "2013-07-08",
"count": 1
},
{
"date": "2013-10-01",
"count": 1
},
{
"date": "2013-10-12",
"count": 1
},
{
"date": "2013-10-30",
"count": 1
},
{
"date": "2013-11-14",
"count": 1
},
{
"date": "2014-01-01",
"count": 1
},
{
"date": "2014-01-03",
"count": 1
},
{
"date": "2014-01-08",
"count": 1
},
{
"date": "2014-04-03",
"count": 1
},
{
"date": "2014-04-17",
"count": 1
},
{
"date": "2014-04-20",
"count": 1
},
{
"date": "2014-04-23",
"count": 1
},
{
"date": "2014-06-07",
"count": 1
},
{
"date": "2014-07-21",
"count": 1
},
{
"date": "2014-07-31",
"count": 1
},
{
"date": "2014-08-01",
"count": 1
},
{
"date": "2014-08-31",
"count": 1
},
{
"date": "2014-09-01",
"count": 1
},
{
"date": "2014-09-24",
"count": 1
},
{
"date": "2014-11-21",
"count": 1
},
{
"date": "2014-12-19",
"count": 1
},
{
"date": "2015-02-07",
"count": 1
},
{
"date": "2015-03-04",
"count": 1
},
{
"date": "2015-05-19",
"count": 1
},
{
"date": "2015-07-23",
"count": 1
},
{
"date": "2015-08-08",
"count": 1
},
{
"date": "2015-08-11",
"count": 1
},
{
"date": "2015-09-21",
"count": 1
},
{
"date": "2015-10-15",
"count": 1
},
{
"date": "2015-11-05",
"count": 1
},
{
"date": "2015-11-09",
"count": 2
},
{
"date": "2015-11-24",
"count": 1
},
{
"date": "2015-12-21",
"count": 1
},
{
"date": "2016-02-18",
"count": 1
},
{
"date": "2016-02-26",
"count": 2
},
{
"date": "2016-03-11",
"count": 1
},
{
"date": "2016-04-06",
"count": 1
},
{
"date": "2016-04-15",
"count": 1
},
{
"date": "2016-06-26",
"count": 1
},
{
"date": "2016-07-20",
"count": 2
},
{
"date": "2016-08-10",
"count": 1
},
{
"date": "2016-08-16",
"count": 1
},
{
"date": "2016-09-28",
"count": 1
},
{
"date": "2016-11-04",
"count": 1
},
{
"date": "2016-12-11",
"count": 1
},
{
"date": "2016-12-19",
"count": 1
},
{
"date": "2017-02-27",
"count": 1
},
{
"date": "2017-03-09",
"count": 1
},
{
"date": "2017-04-03",
"count": 1
},
{
"date": "2017-04-08",
"count": 1
},
{
"date": "2017-04-10",
"count": 1
},
{
"date": "2017-05-17",
"count": 1
},
{
"date": "2017-06-16",
"count": 1
},
{
"date": "2017-06-27",
"count": 1
},
{
"date": "2017-07-27",
"count": 1
},
{
"date": "2017-10-04",
"count": 1
},
{
"date": "2017-12-23",
"count": 1
},
{
"date": "2018-02-12",
"count": 1
},
{
"date": "2018-02-16",
"count": 1
},
{
"date": "2018-02-26",
"count": 1
},
{
"date": "2018-04-28",
"count": 1
},
{
"date": "2018-06-20",
"count": 1
},
{
"date": "2018-08-03",
"count": 1
},
{
"date": "2018-10-03",
"count": 1
},
{
"date": "2018-11-06",
"count": 1
},
{
"date": "2019-01-09",
"count": 1
},
{
"date": "2019-02-01",
"count": 1
},
{
"date": "2019-03-07",
"count": 1
},
{
"date": "2019-03-31",
"count": 1
},
{
"date": "2019-05-17",
"count": 1
},
{
"date": "2019-07-10",
"count": 1
},
{
"date": "2019-08-11",
"count": 1
},
{
"date": "2020-02-19",
"count": 1
},
{
"date": "2020-06-16",
"count": 1
},
{
"date": "2020-07-22",
"count": 1
},
{
"date": "2020-08-29",
"count": 1
},
{
"date": "2022-01-31",
"count": 1
},
{
"date": "2023-06-02",
"count": 1
},
{
"date": "2023-06-24",
"count": 1
},
{
"date": "2024-05-02",
"count": 1
},
{
"date": "2024-05-12",
"count": 1
},
{
"date": "2024-05-13",
"count": 1
},
{
"date": "2024-05-14",
"count": 1
},
{
"date": "2024-12-18",
"count": 1
},
{
"date": "2025-06-15",
"count": 1
},
{
"date": "2025-10-03",
"count": 1
},
{
"date": "2025-12-25",
"count": 1
},
{
"date": "2026-01-15",
"count": 1
},
{
"date": "2026-02-10",
"count": 1
},
{
"date": "2026-04-21",
"count": 1
},
{
"date": "2026-05-23",
"count": 2
},
{
"date": "2026-05-24",
"count": 1
},
{
"date": "2026-05-25",
"count": 7
},
{
"date": "2026-05-30",
"count": 1
}
],
"complete": true,
"collected": 172,
"total_stars": 172
},
"open_issues_and_prs": 0
},
"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": 30160,
"source_files_sampled": 80,
"oversized_source_files": 0,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"Gemfile"
],
"advisories": {
"error": "No resolved dependencies carried a version and a supported ecosystem",
"scope": "repository_graph",
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 22,
"direct_affected_count": 0
},
"ecosystems": [
"rubygems"
],
"dependencies": [
{
"name": "libxml-ruby",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": null
},
{
"name": "nokogiri",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": null
},
{
"name": "oga",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 2.3"
},
{
"name": "ox",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": null
},
{
"name": "rexml",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": null
},
{
"name": "minitest",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 6"
},
{
"name": "minitest-mock",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 5.27"
},
{
"name": "mutant-minitest",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 0.14.1"
},
{
"name": "rake",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 13.3.1"
},
{
"name": "rbs",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 4.0.0"
},
{
"name": "rdoc",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 7.0.2"
},
{
"name": "rdoc",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 7.0.2"
},
{
"name": "rubocop",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 1.81.7"
},
{
"name": "rubocop-minitest",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 0.36"
},
{
"name": "rubocop-performance",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 1.26.1"
},
{
"name": "rubocop-rake",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 0.7.1"
},
{
"name": "simplecov",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 1"
},
{
"name": "standard",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 1.52"
},
{
"name": "standard-performance",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 1.9"
},
{
"name": "steep",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 2"
},
{
"name": "yard",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 0.9.38"
},
{
"name": "yardstick",
"manifest": "Gemfile",
"ecosystem": "rubygems",
"version_constraint": ">= 0.9.9"
}
],
"all_dependencies": {
"error": null,
"source": "github-sbom",
"packages": [
{
"name": "libxml-ruby",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "minitest",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "minitest-mock",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "mutant-minitest",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "nokogiri",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "oga",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "ox",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "rake",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "rbs",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "rdoc",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "rexml",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "rubocop",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "rubocop-minitest",
"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": "simplecov",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "standard",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "standard-performance",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "steep",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "yard",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "yardstick",
"direct": true,
"version": null,
"ecosystem": "rubygems"
},
{
"name": "bigdecimal",
"direct": false,
"version": null,
"ecosystem": "rubygems"
}
],
"collected": true,
"truncated": false,
"total_count": 22,
"direct_count": 21,
"indirect_count": 1
}
},
"maintainership": {
"issues": {
"open_prs": 0,
"merged_prs": 33,
"open_issues": 0,
"closed_ratio": 1,
"closed_issues": 34,
"closed_unmerged_prs": 8
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "sferik",
"commits": 401,
"avatar_url": "https://avatars.githubusercontent.com/u/10308?v=4"
},
{
"type": "User",
"login": "ohler55",
"commits": 16,
"avatar_url": "https://avatars.githubusercontent.com/u/118856?v=4"
},
{
"type": "User",
"login": "phiggins",
"commits": 6,
"avatar_url": "https://avatars.githubusercontent.com/u/22962?v=4"
},
{
"type": "User",
"login": "joshk",
"commits": 4,
"avatar_url": "https://avatars.githubusercontent.com/u/8701?v=4"
},
{
"type": "User",
"login": "Earlopain",
"commits": 3,
"avatar_url": "https://avatars.githubusercontent.com/u/14981592?v=4"
},
{
"type": "User",
"login": "hakanensari",
"commits": 3,
"avatar_url": "https://avatars.githubusercontent.com/u/31693?v=4"
},
{
"type": "User",
"login": "koic",
"commits": 3,
"avatar_url": "https://avatars.githubusercontent.com/u/13203?v=4"
},
{
"type": "User",
"login": "koraktor",
"commits": 3,
"avatar_url": "https://avatars.githubusercontent.com/u/66112?v=4"
},
{
"type": "User",
"login": "ka8725",
"commits": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/243846?v=4"
},
{
"type": "User",
"login": "fisherwebdev",
"commits": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/169760?v=4"
}
],
"contributors_sampled": 20,
"top_contributor_share": 0.879
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"benchmark.yml",
"docs.yml",
"linter.yml",
"mutant.yml",
"push.yml",
"tests.yml",
"typecheck.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": null,
"reason": "no pull request found",
"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/30 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 16 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": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 10,
"reason": "30 commit(s) and 2 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": 10,
"reason": "packaging workflow 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": 0,
"reason": "no SAST tool detected",
"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": "391efee2f509a7afde833eee8315f0ec7f59f16b",
"ran_at": "2026-07-22T01:58:58Z",
"aggregate_score": 4.5,
"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-13T21:09:52Z",
"oldest_open_prs": [],
"last_merged_pr_at": "2026-04-22T22:23:11Z",
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/sferik/multi_xml",
"host": "github.com",
"name": "multi_xml",
"owner": "sferik"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 65,
"inputs": {
"security": 45,
"vitality": 71,
"community": 70,
"governance": 68,
"engineering": 68
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 71,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "moderate",
"name": "Development activity",
"note": null,
"notes": [],
"value": 62,
"inputs": {
"commits_last_year": 80,
"human_commit_share": 1,
"days_since_last_push": 8,
"active_weeks_last_year": 9
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 8 days ago",
"points": 28.8,
"status": "partial",
"details": [
{
"code": "push_recency",
"params": {
"days": 8
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "9/52 weeks with commits",
"points": 6.2,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 9
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "80 commits in the last year",
"points": 17.1,
"status": "partial",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 80
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "30 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 10",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "good",
"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": 84,
"inputs": {
"releases_count": 1,
"latest_release_tag": "v0.9.1",
"releases_from_tags": false,
"days_since_latest_release": 78,
"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 78 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 78
}
}
],
"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": 8,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "last human commit 8 days ago",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_maintained",
"params": {
"days": 8
}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "good",
"name": "Community & Adoption",
"value": 70,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "moderate",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 52,
"inputs": {
"forks": 38,
"stars": 172,
"watchers": 4,
"growth_state": "organic",
"growth_factor_pct": 100
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "172 stars",
"points": 36.2,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 172
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "38 forks",
"points": 13.1,
"status": "partial",
"details": [
{
"code": "forks",
"params": {
"count": 38
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "4 watchers",
"points": 2.7,
"status": "partial",
"details": [
{
"code": "watchers",
"params": {
"count": 4
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "good",
"name": "Community health",
"note": null,
"notes": [],
"value": 70,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": true,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"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": 0,
"status": "missed",
"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": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
},
{
"key": "ecosystem_adoption",
"band": "excellent",
"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": 100,
"inputs": {
"packages": [
"multi_xml"
],
"dependents": null,
"ecosystems": "rubygems",
"total_downloads": 583709139,
"monthly_downloads": null
},
"components": [
{
"key": "total_downloads",
"name": "Total downloads",
"detail": "583,709,139 downloads all-time across rubygems",
"points": 80,
"status": "met",
"details": [
{
"code": "downloads_total",
"params": {
"count": 583709139,
"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": 68,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "at_risk",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 35,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 20,
"top_contributor_share": 0.879
},
"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 88% of commits",
"points": 2.7,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 88
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "20 contributors",
"points": 13.5,
"status": "met",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 20
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 16 contributing companies or organizations",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "good",
"name": "Issue & PR responsiveness",
"note": null,
"notes": [],
"value": 78,
"inputs": {
"merged_prs": 33,
"open_issues": 0,
"closed_issues": 34,
"issue_closed_ratio": 1,
"closed_unmerged_prs": 8
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "100% of issues closed",
"points": 46.8,
"status": "met",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 100
}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "33/41 decided PRs merged",
"points": 30.8,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 33,
"decided": 41
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "good",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 74,
"inputs": {
"followers": 2649,
"owner_type": "User",
"is_verified": null,
"owner_login": "sferik",
"public_repos": 216,
"account_age_days": 6642
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "2,649 followers of sferik",
"points": 24.6,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 2649,
"login": "sferik"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "216 public repos, account ~18 yr old",
"points": 25,
"status": "met",
"details": [
{
"code": "public_repos",
"params": {
"count": 216
}
},
{
"code": "account_age_years",
"params": {
"years": 18
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"multi_xml"
],
"ecosystems": "rubygems",
"any_deprecated": false,
"min_days_since_publish": 78
},
"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 78 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 78
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "29 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 29
}
}
],
"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": "moderate",
"name": "Engineering Quality",
"value": 68,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "good",
"name": "Engineering practices",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 80,
"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": "7 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 7
}
}
],
"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": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"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": 45,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): CI-Tests, Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"ci_tests",
"signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 45,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 16,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 2,
"scorecard_aggregate": 4.5
},
"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": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"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/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 16 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 detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "30 commit(s) and 2 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 detected",
"points": 5,
"status": "met",
"details": [],
"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": "no SAST tool detected",
"points": 0,
"status": "missed",
"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": 20
},
"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": "at_risk",
"name": "AI Readiness",
"value": 32,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "critical",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 18,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.34,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"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": "34 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 18.1,
"status": "partial",
"details": [
{
"code": "legible_history",
"params": {
"legible": 34,
"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": 30160,
"source_files_sampled": 80,
"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/80 source files over 60KB",
"points": 55,
"status": "met",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 80,
"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": [
"No resolved dependencies carried a version and a supported ecosystem"
],
"report_type": "repository",
"generated_at": "2026-07-22T01:59:09.869304Z",
"schema_version": "0.26.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/s/sferik/multi_xml.svg",
"full_name": "sferik/multi_xml",
"license_state": "standard",
"license_spdx": "MIT"
}