). Previously any line beginning with `..` was\nrejected as a title, so the marker line became a paragraph and the\nfollowing block lost its title.\n\nCloses #957\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Recognize block title with a leading period (`..name`) (#958)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-25T15:51:18Z", "body_truncated": false, "is_coding_agent": true }, { "oid": "320ce4bdfac06a8ba4b9a1e1c684c0587ee43276", "body": null, "is_bot": false, "headline": "chore(asciidoc-parser): release v0.27.0 (#941)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-25T04:25:25Z", "body_truncated": false, "is_coding_agent": false }, { "oid": "aa767ff5cde506e86b4361ababa6c0266d9c44ac", "body": "* fix: capture block metadata on list items instead of dropping it\n\n`ListBlock::parse` built each list item with an empty `BlockMetadata`, so a\ntitle, anchor, or attribute list written directly before a list item's marker\nwas silently discarded. Worse, because the empty metadata could not parse past\n[…]\nt for them, restoring the original fast path for\nthe common paragraph case.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Capture block metadata on list items instead of dropping it (#954)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-25T04:22:04Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "c4c7294195664e7d3005c7cc48796c9a2fdc9fcd", "body": "* chore: Pin GitHub Actions to specific commit SHAs\n\nReplace mutable version tags with pinned commit SHAs (each with a\ntrailing version comment) across ci.yml and pr_title.yml, following the\npattern already used in release.yml. Each SHA is the commit its tag or\nbranch currently resolves to. This har\n[…]\n currently resolves to) so all\nthree workflows share a single checkout SHA.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore: Pin GitHub Actions to specific commit SHAs (#955)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-25T04:04:49Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "b34f99e95e10c41ff93d4c26edf3ae455560998c", "body": "Part of the #939 TEMPORARY-marker audit. The `#[allow(...)]` attributes\nguarding test scaffolding are no longer warranted:\n\n- `assert_dom/virtual_dom.rs`: the `VirtualNode` builder helpers are now\n used throughout the DOM assertions, so the blanket `#[allow(dead_code)]`\n on the impl block is remov\n[…]\nunconstructed, so per the audit guidance they (and their\n `Debug` / equality arms) are removed rather than left behind an allow.\n\nCloses #949.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore: Remove consumed 'while building' scaffolding allows (#949) (#952)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-25T03:42:14Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "8944d9105400fdba9e9d7fa29d266ad1ecf38818", "body": "…o_name (#953)\n\n`Span::take_ident` borrowed Rust's identifier definition (leading\nalphabetic/underscore, then alphanumerics/underscores) because\n\"identifier\" is not crisply defined in the AsciiDoc documentation. Its\nuse was already discouraged in favor of more specific helpers.\n\nThere was a single c\n[…]\nng digit) is now parsed and then rejected as unrecognized\nrather than rejected at the name-capture stage, with identical results.\n\nCloses #948.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "refactor: Replace Span::take_ident with spec-grounded take_block_macr…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-25T03:40:42Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "78d9373b0f7d80bbd965d48ec60c5924b6592832", "body": "…947) (#951)\n\nThe `Block` enum's variants have converged in size as the parser\nevolved. The two largest, `Section` (568 bytes) and `Media` (536\nbytes), now differ by only 32 bytes – far under clippy's 200-byte\n`large_enum_variant` threshold – so the lint no longer fires. The\n`#[allow]` (carried forw\n[…]\nasoning already\ndocumented on `BlockParseOutcome`).\n\nVerified with the CI invocation\n`cargo clippy --all-features --all-targets -- -Dwarnings`.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore: Drop stale allow(clippy::large_enum_variant) on Block (close #…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-25T03:40:16Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "19faf3b5696dfb32a0f875f4d95ddb93db7a8706", "body": "Audit the code base for TEMPORARY / \"while building\" markers (excluding\n`ref` and tests quoting `ref` content) and convert the genuine ones to\nTODO comments that link to tracking issues, per #939.\n\n- List items discard block metadata (#946).\n- `Block` enum trips `clippy::large_enum_variant` (#947).\n- `Span::take_ident` uses a provisional identifier definition (#948).\n- Remove \"while building\" scaffolding allows once consumed (#949).\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore: replace TEMPORARY markers with issue-linked TODOs (#950)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-25T03:19:25Z", "body_truncated": false, "is_coding_agent": true }, { "oid": "5fdf0f42b24c7d41e72c1df86811d1789cd3eaba", "body": "Code-coverage review for dead code found no removable dead code: line\ncoverage is 98.79% and the compiler's dead_code lint is clean. The\nuncovered product lines are all intentional guardrails (defensive\nbranches, assertions, Debug impls, and a refactor-blocked region).\n\nThe one actionable cleanup is this stale attribute: the re-export is now\nused via crate::document::DuplicateIdError in the parser, so the\nallow(unused) suppresses nothing.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore: Remove stale allow(unused) on DuplicateIdError re-export (#945)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T23:05:40Z", "body_truncated": false, "is_coding_agent": true }, { "oid": "4bbb8fe9f0018185442bda7a16e44b199f8a8e60", "body": "…haustive (#940)\n\n* feat: Derive Hash on the public AST / output types\n\nSpan, Block, Content, WarningType and the types reachable from them now\nimplement Hash, so blocks and spans can key a HashMap/HashSet and warnings can\nbe bucketed by type. ResolvedAttributes hashes an order-independent summary o\n[…]\nleValue / ModificationContext fields, all of which hold only Hashable\ndata.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "feat: Derive Hash on the public AST/output types; mark Warning non_ex…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T21:39:56Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "a59f603280d80c729d8a0f80afdb3554901d187b", "body": "…pat 5.0.0 -> 5.0.1 (#938)\n\nPatch-level updates to the benchmark harness dev-dependencies. Raising the\ndeclared floors keeps the -Z direct-minimal-versions CI job on the current\npatch releases. Benchmarks compile and minimal-versions resolves cleanly.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore(deps): Bump criterion 0.8.0 -> 0.8.2 and codspeed-criterion-com…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T19:03:52Z", "body_truncated": false, "is_coding_agent": true }, { "oid": "ca8db26179c0fe77d71e8e55b3a358fde32945af", "body": "* chore(asciidoc-parser): release v0.26.0\n\n* docs: Add 0.26.0 breaking changes guide to the changelog\n\nDocument the source-level migration for the four breaking changes in\n0.26.0 (block traversal #930, PathResolver-as-trait #934, rendering API\npolish #929, and the SourceMap reshape #917), mirroring the prose\nguide added for 0.23.0.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore(asciidoc-parser): release v0.26.0 (#916)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T15:52:19Z", "body_truncated": false, "is_coding_agent": true }, { "oid": "50f68b5578c980dbfe90d73256b5b3e3e8b27f97", "body": "…ers (close #896) (#933)\n\n* feat: Let a custom InlineSubstitutionRenderer override only what differs (close #896)\n\nTwo changes unblock a downstream (e.g. Zola) `InlineSubstitutionRenderer`:\n\n- Give every `InlineSubstitutionRenderer` method a default body that\n delegates to the built-in `HtmlSubstit\n[…]\n is not surprised that `render_icon` and a direct `icon_uri`\ncall disagree.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "feat: Let a custom InlineSubstitutionRenderer override only what diff…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T15:42:28Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "104ed44bd5ba50724bb852dbc58f9d423dcb9105", "body": "Warnings were deterministic but assembled by category (header, blocks,\npreprocessor, substitution, post-parse checks, then reference-resolution\nwarnings appended last), so an unresolved `include::` on an early line\ncould sort after a malformed inline macro further down, and unresolved-xref\nwarnings \n[…]\ne parse and after\na reference-resolution sweep folds its warnings in, so `warnings()` now\nyields line-ordered, still-deterministic diagnostics.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Emit document warnings in source order (close #901) (#932)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T15:06:54Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "0202092e25f780df3441880c100fca1f2ed8082b", "body": "…(#936)\n\nPRs #930 (child_blocks API) and #934 (PathResolver trait) landed\nconcurrently without a rebase, leaving the with_path_resolver test\ncalling the removed Document::nested_blocks(). Point it at\nchild_blocks() to match the sibling call sites.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Repair stale nested_blocks() call left by concurrent PR landing …", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T14:36:01Z", "body_truncated": false, "is_coding_agent": true }, { "oid": "e454b6e3c8507d1dc916f572a55b0d13de7b22ad", "body": "…k=self (close #919) (#927)\n\n* fix: Reject a dangerous image/icon target promoted to an href via link=self (close #919)\n\nAn `image:`/`icon:` macro whose target carries a script-capable scheme\n(`javascript:`, `vbscript:`, or a non-image `data:` such as\n`data:text/html,…`) is harmless in the `\u003cimg src\n[…]\nage data URIs and trusted embedded SVGs (the Asciidoctor-parity case) live.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Reject a dangerous image/icon target promoted to an href via lin…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T14:27:49Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "08944ce4a76acacdb4515e1b549df4728080162e", "body": "…r (close #898) (#934)\n\nPath resolution was the one extensibility seam in the crate that could not\nbe swapped: `PathResolver` was a concrete struct exposed as a `pub` by-value\nfield on `Parser`, so an Antora/Zola-style host needing custom path or URL\nrewriting (virtual filesystems, content roots, UR\n[…]\n` field is now `pub(crate) Rc\u003cdyn PathResolver>`,\nconfigured through a new `with_path_resolver(...)` builder rather than direct\nfield mutation.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "refactor!: Make PathResolver a trait with a with_path_resolver builde…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T14:21:36Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "d01724d237725af16b2892d5572cc95e102b7443", "body": "…I (close #894) (#930)\n\n* feat!: replace IsBlock::nested_blocks with a complete child_blocks API (close #894)\n\nThe discoverable block accessor `IsBlock::nested_blocks()` silently omitted\nMarkdown-blockquote children (reachable only via `QuoteBlock::blocks()`) and\nAsciiDoc table-cell content, so tool\n[…]\nck`, and\n the `nth` override) generated by the `opaque_slice_iter!` macro.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "feat!: Replace IsBlock::nested_blocks with a complete child_blocks AP…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T14:18:52Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "6dbdb248bb87626baa8087ac7c6ef5cbc0f52de9", "body": "…#903) (#931)\n\n* fix: Enforce SourceMap append ordering with a debug assertion (close #903)\n\n`SourceMap::resolve` binary-searches `segments` by `output_line`, which\nsilently returns garbage on an unsorted slice. `append` documented that\nentries \"should\" arrive in increasing order but did not enforce\n[…]\nptile-apps[bot]@users.noreply.github.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>\nCo-authored-by: greptile-apps[bot] \u003c165735046+greptile-apps[bot]@users.noreply.github.com>", "is_bot": false, "headline": "fix: Enforce SourceMap append ordering with a debug assertion (close …", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T14:14:12Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "5cb17dc58929cd6e654764f8b50a06e222229607", "body": "…se #899) (#926)\n\n`Catalog::ids()` and `Catalog::entries()` iterated a randomly-seeded\n`HashMap`, so their order varied between process runs. A multi-document\npipeline that derives output from catalog iteration order (e.g. building a\nglobal cross-reference index, or resolving a collision as \"first s\n[…]\nookups. `DebugHashMapFrom` is generalized to render either map type and\nstill sorts its own output, so the `Debug` representation is unchanged.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Make catalog ID iteration deterministic across process runs (clo…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T14:02:54Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "7f1df812544eadf0f48551d0b98abfba3a438e77", "body": "…e #906) (#925)\n\nThe doc comment read only \"Alternative to\" with a TODO placeholder. Describe\nthat `LookaheadReplacer` is an alternative to `regex::Replacer` that can inspect\nthe text following a match and reject it via `SkipAheadAndRetry`, modeling the\nlook-ahead pattern that `regex::Replacer` cannot express.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "docs: Complete the truncated doc comment on `LookaheadReplacer` (clos…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T13:34:38Z", "body_truncated": false, "is_coding_agent": true }, { "oid": "8eef1e68450f576f513f568f1a1a33d8daf724ff", "body": "…K branch (close #908) (#928)\n\nThe invalid-macro-syntax `else` branch in `InlineLinkReplacer` carried a\nFIXME noting that a `link:` prefix should never reach it: the shared\nNON-ANGLE branch of `INLINE_LINK` let `link:` prefix a bare (bracket-less)\nURL, which then matched and was rejected as invalid \n[…]\nsyntax path.\n\n`NormalizedCaps` gains a third branch mapping and `bare` becomes optional\n(the LINK-MACRO branch always has a trailing attrlist).\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "refactor: Give the `link:` prefix its own bracket-required INLINE_LIN…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T13:32:34Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "024721f9252180c4962152effea6365cc966c97d", "body": "Settles several pre-1.0 public-API commitments flagged in the adversarial\nreview, each of which would become a breaking change to fix after the freeze:\n\n- Rename the misspelled trait method\n `InlineSubstitutionRenderer::render_quoted_substitition` to\n `render_quoted_substitution`.\n- Remove the pro\n[…]\n type and\n`LinkRenderParams::type_` field are removed; and `LinkRenderParams::window`\nchanges from `Option\u003c&'static str>` to `Option\u003c&'a str>`.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "refactor!: Polish public rendering API ahead of 1.0 (close #897) (#929)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T13:30:31Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "91abb32cc09f6a331ac1c2898655248cb54037be", "body": "…ion (close #889) (#920)\n\nAdd a prominent \"Security: rendering untrusted input\" section to the\nREADME (which is also the crate-level doc via `include_str!`), stating\nthat the HTML renderer is not a sanitizer, that attribute-reference\nsubstitution and passthroughs emit raw HTML by design, and that\nco\n[…]\noc must run the output\nthrough an HTML sanitizer such as `ammonia`. Clarify that safe mode\ngoverns file/environment reach, not output escaping.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "docs: Document that untrusted AsciiDoc output requires HTML sanitizat…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T05:14:55Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "870609273fe4653c8dd8ecea622099c3543654ff", "body": "…05) (#924)\n\n* perf: Reduce allocations in the inline substitution pipeline (close #905)\n\nResidual allocation-reduction items from the adversarial review; each is\nsmall and mechanical, and the many-small-blocks-of-plain-prose throughput\ncase benefits from all of them.\n\n- `apply_special_characters` n\n[…]\nng both the\n no-op-filter borrow branch and the changed-text owned branch.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Reduce allocations in the inline substitution pipeline (close #9…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T05:14:23Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "e053106f32bb6358554dfd2f3fc584574ff3e393", "body": "…ounds slice (close #902) (#923)\n\n* fix: Fall back to an empty span instead of the whole span on out-of-bounds slice (close #902)\n\n`Span::slice` / `slice_from` / `slice_to` guarded their bounds only with a\n`debug_assert!`. In a release build, when `.get(range)` returned `None`, the\n`map_or(*self, …)\n[…]\nes;\nthe release fallback behavior is already covered by the `empty()` test.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Fall back to an empty span instead of the whole span on out-of-b…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T05:13:38Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "6ad42b74d3ae456eeccab4f1f7a6dc8504208804", "body": "…ciiDoc table cells (close #904) (#922)\n\nFor every AsciiDoc-style (`a`) table cell, `process_content` rebuilt the\nattribute-lock set from scratch, allocating an owned `String` for each of the\n~74 built-in attributes it locked and deep-cloning the whole `HashSet\u003cString>`\nper cell. This was the domina\n[…]\ncall out of the modifiable-attributes loop so the\nper-parser attribute map is made-mut once per cell rather than re-checked on\nevery iteration.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "perf: Avoid per-cell String allocations when locking attributes in As…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T05:07:35Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "24ec6d181229f6d09f8dccdcf646fbd5ef918cad", "body": "…or (close #907) (#921)\n\nThe `// TODO:` in `section_to_node` described how the section title heading is\nadded in the `Block::Section` match arm (using `section.level()` for the heading\nlevel and `section.section_title()` for the text). That behavior is already fully\nimplemented there, so the note tr\n[…]\nfold its one useful detail (the title heading, like the id,\nlands on the heading rather than the wrapper `\u003cdiv>`) into the surrounding\ncomment.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore: Remove stale TODO restating implemented section-heading behavi…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T05:07:00Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "80825d50579108831d9bc1f96f5a6e9e43d86cdd", "body": "…idelity (#917)\n\n* feat: Map preprocessed spans back to origin file, line, column, and fidelity (close #891)\n\nSpans carry coordinates relative to the single preprocessed buffer, and the\nonly way back to an origin was `SourceMap::original_file_and_line`, which is\nline-only and cannot say whether a li\n[…]\nhe included file's identity is\nnot carried forward into the parent's lines.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "feat: Map preprocessed spans back to origin file, line, column, and f…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T04:47:54Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "e64f4ade1fff3da5fba49aebf0aba8c2fb15d6dd", "body": "…k macro (close #888) (#911)\n\n* fix: Escape href/target/icon attributes and reject script URIs in link macro (close #888)\n\nSeveral `href`/`target` and icon attribute values were emitted into the\nrendered HTML without escaping the `\"` delimiter, allowing an author to\nbreak out of the attribute and in\n[…]\nnd `render_icon_or_image` (which drops the\nlive link) share one definition.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Escape href/target/icon attributes and reject script URIs in lin…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T01:59:19Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "0c93961c8288c853f6300d9487cb0139a3afe9b2", "body": "A UTF-8 byte-order mark (`EF BB BF` = U+FEFF) at the start of the input\nwas not stripped. `preprocess` short-circuits and returns the source\nunchanged when there are no directives, so the U+FEFF became the first\ncharacter of the first line. `Header::parse` requires the line to start\nwith `= `, so a \n[…]\n This matches Asciidoctor, which strips a UTF-8 BOM even\nfor UTF-8 input, and is independent of UTF-16 transcoding, which remains\nout of scope.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Strip a leading UTF-8 BOM before parsing (close #900) (#918)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T01:45:04Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "436d8144f64c066572d62d4581da228bf52601ec", "body": "…nput (close #885) (#910)\n\n* fix: Cap block nesting depth to prevent stack overflow on untrusted input (close #885)\n\nBlock parsing descends recursively through `parse_blocks_until` (delimited\nblock bodies, section bodies, table cells, quote/blockquote content) and\nthrough `ListBlock::parse_inside_li\n[…]\ntores parity with\nthe pre-#885 baseline (measured within run-to-run noise).\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Cap block nesting depth to prevent stack overflow on untrusted i…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T01:30:04Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "9c91f6f9c6f3916cb55ae67e3fbfeccfb3bfa644", "body": "…r (close #893) (#909)\n\n* fix: Reset document attribute values between parses on a reused Parser (close #893)\n\n`Parser::parse_deferred` reset the catalog, callouts, substitution\nwarnings, section numbering, pending block title, and counters between\nparses but not `attribute_values`, so document-head\n[…]\nic's prose dash convention in the doc comment added by the\nprevious commit.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Reset document attribute values between parses on a reused Parse…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T01:08:35Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "c8aa0e203b0f9a0374a288eab5fcd69524e2134d", "body": "…ad (close #887) (#912)\n\n* fix: Honor char boundary when skipping constrained-monospace look-ahead (close #887)\n\nThe constrained-monospace quote regex's leading boundary group\n`[^\\w&;:\"'`}]` matches any non-word Unicode scalar, including multi-byte\ncharacters. When a failed look-ahead skipped the le\n[…]\nage gap left by\nthe multi-byte fix. The escaped text is preserved verbatim.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Honor char boundary when skipping constrained-monospace look-ahe…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T00:40:36Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "50f578e127fe1a0c76989d01cbf6a21aa8b9a28c", "body": "Apply the documented comment/doc style conventions to hand-written\ncomments and documentation text (excluding the vendored `ref/` tree and\nthe tests that quote it):\n\n- Convert prose em dashes to spaced en dashes (366 lines). The one\n literal em-dash character reference in `virtual_dom.rs` is preser\n[…]\nn test it marks.\n- File tracking issues for an incomplete doc comment and two unlinked\n TODO/FIXME comments, and link them (#906, #907, #908).\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "doc: Normalize comment and doc prose style across the codebase (#915)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T00:37:00Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "a43b990ea8278c9b81394ffd2bff232a57b17a60", "body": "…#886) (#914)\n\n* fix: Avoid O(n²) parse time on many repeated block delimiters (close #886)\n\n`QuoteBlock::parse` runs before `CompoundDelimitedBlock` in block dispatch,\nso it is tried for every delimiter line. Its quoted-paragraph path called\n`read_paragraph` (a scan to the next blank line) before t\n[…]\nlines between\nthem) — the shape that previously triggered O(n²) parse time.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Avoid O(n²) parse time on many repeated block delimiters (close …", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T00:35:44Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "b5252cb2a4b00dd2dd93049da95c2c90d2178eb9", "body": "…ction (close #890) (#913)\n\nThe `Safe` and `Server` docstrings described protections the parser does\nnot actually enforce:\n\n- `Safe` claimed it prevents access to files outside the source file's\n parent directory. This crate performs no filesystem I/O and does not\n port Ruby Asciidoctor's `PathRes\n[…]\nent handler's responsibility —\nand that only `Secure`, not `Server`, disables include/asset embedding.\n\nDocumentation only; no behavior change.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "docs: Correct SafeMode Safe/Server docstrings to match enforced prote…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-24T00:28:44Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "006b8752176d0637c7f3c2535ecbb02f5ba47798", "body": null, "is_bot": false, "headline": "chore(asciidoc-parser): release v0.25.0 (#879)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T15:21:24Z", "body_truncated": false, "is_coding_agent": false }, { "oid": "cfae1bd47ba42ecab7e0585b59f9f80fa7a40c81", "body": null, "is_bot": false, "headline": "chore: Update README to reflect fully feature-complete status (#884)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T15:15:18Z", "body_truncated": false, "is_coding_agent": false }, { "oid": "b2106856ea6c1c62dcd52c1021720ca2d7b5d294", "body": "…(close #871) (#883)\n\n* test: Verify link attrlist enclosure rule for invalid attribute names (close #871)\n\nPromote the \"enclosure only required when the text preceding the equals\nsign matches a valid attribute name\" sentence in the link/URL macro\nattribute-parsing spec from a non-normative note to \n[…]\nor future spec-coverage work and silence the\nunused-macro/-import warnings.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Verify link attrlist enclosure rule for invalid attribute names …", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T15:04:32Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "48407cc93dcdb2524698690360334ec80e85f99e", "body": "… content (close #877) (#881)\n\n`reindent_included_lines` previously returned included content unchanged\nwhenever the `indent` attribute was absent, so `tabsize`-driven tab\nexpansion only fired when `indent` was also supplied.\n\nPer the spec, when `tabsize` is set, tabs are replaced with spaces\nregard\n[…]\nxpansion now runs\nwhenever `tabsize` is positive; indentation normalization is applied\nindependently when `indent` is present and non-negative.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Expand tabs from `tabsize` independently of `indent` on included…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:53:49Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "1c10c0badc6182a1de62af87f02a150e2f994d42", "body": "…ing blank lines (close #876) (#882)\n\nPromote the `to_do_verifies!` block in `document_test.rs` to two real\n`verifies!` tests, backed by an `InlineFileHandler` fixture reproducing\nAsciidoctor's canonical `include-with-leading-blank-line.adoc` (two blank\nlines before the level-0 title).\n\n- A whole-fi\n[…]\ne and sets `:toc:`.\n- `lines=6` selects by original line number, skipping the leading blank\n lines and the title so only the section survives.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "test: Verify document-title & lines= selection for includes with lead…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:53:02Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "de9a4cff700cb105ba39c66753cc902e78bfc5a7", "body": "…lose #801) (#880)\n\n`WarningType` became part of the public API in #799, so its variant names\nand `Display` strings now need to read as a deliberate, consistent set. This\nis the one-time review the long-standing TODO above `InvalidMacroName` asked\nfor.\n\nVariant renames (breaking for anyone matching \n[…]\ner\"). Wording is otherwise unchanged. This changes user-visible\nwarning text.\n\nThe `TODO (#801)` marker is removed now that the review is done.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "refactor(warnings)!: Review WarningType variant names and messages (c…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:44:50Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "0c6a48c7687d434f46b001a991b9aaae7ca4f778", "body": "…878)\n\nConvert the now-testable table structural-container row to verifies! and\nreclassify the permanently-unverifiable / out-of-scope blocks as\nnon_normative! with justifications:\n\n- delimited.rs: the four table delimiters (`|===`, `,===`, `:===`, `!===`)\n now assert the `table` context and conten\n[…]\ne two genuinely-deferred blocks now cite tracking issues #876 (include\ndoctitle recognition / lines= selection) and #877 (block-level tabsize).\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "test: Resolve remaining to_do_verifies! blocks from the #628 sweep (#…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:39:38Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "2f37e9dd217d6c7595c77300828d290df3b15aaa", "body": "…) (#874)\n\n* test: Cover description-list delimiter and anchor rules (close #864)\n\nThe opening `non_normative!` block in `lists/description.rs` reproduced\nseveral normative parsing rules for description lists but none were\nexercised by a test. Split the block so the normative prose is now backed\nby \n[…]\ntrast to\na leading `[[id]]` anchor which becomes part of the rendered term.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": " chore: Cover description-list delimiter and anchor rules (close #864…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:37:26Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "3e721feddf89a868c943c97bf3abb78d0b32387a", "body": "…horthand ID/role order, AsciiDoc-cell directive) (#873)\n\n* test: Cover `title`-attribute fallback for the document title\n\nSplit the `[#title-attr]` `non_normative!` block so the normative\nfallback rule is verified: with no level 0 section title and no\n`doctitle` attribute, a `title` attribute entry\n[…]\name\ndirective on the following line acts as a normal multiline conditional.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore: Close mislabeled-normative coverage gaps (doctitle fallback, s…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:27:21Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "18685312ef868d1f9906882096a40a25a8224b63", "body": "…se #865) (#875)\n\nSeveral inline-macro spec pages wrapped a normative parsing rule in\n`non_normative!` without covering tests. Add `verifies!` coverage for\neach rule the parser already implements correctly, and a justified\n`to_do_verifies!` marker for the one it does not:\n\n- Inline image alt-text: a\n[…]\next before `=` is a valid attribute name. The parser does not yet\n honor this; the marker documents current behavior and is tracked by\n #871.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "test: Cover inline-macro spec rules hidden behind non_normative! (clo…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:26:46Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "9aad9fafcabf48bfd30a115b4693f86279bde551", "body": "…combinators (close #866) (#868)\n\n* test: Cover mixed ifdef/ifndef combinator behavior (close #866)\n\nThe `non_normative!` block in `ifdef_ifndef.rs` stated the normative rule\nthat the `,` (or) and `+` (and) combinators cannot be combined in a single\nconditional-directive expression, but no test asse\n[…]\naffected. Extend `combinators_cannot_be_mixed` to cover the `+`-first case.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Match Asciidoctor's first-delimiter rule for mixed ifdef/ifndef …", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:14:25Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "5051db0ceb815d7961afb2c5fc2d53131d6ee2df", "body": "Port Asciidoctor's `doc.register :links, target` so the parser records\nevery link target it encounters, exposed as `Catalog::links()`. Like the\nimage registry, population is gated on the `catalog_assets` option and\nrecorded in substitution-pass order.\n\nAll four Asciidoctor registration sites are covered: bare-URL autolink,\n`link:` macro, `mailto:`/link macro, and email autolink (the last of\nwhich the original TO DO markers had missed).\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "feat: Populate the document catalog's link registry (close #335) (#872)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:10:34Z", "body_truncated": false, "is_coding_agent": true }, { "oid": "e06f0caf0984685dcb64fa452c10e6ca152a60d2", "body": "Audit of commented-out code turned up two genuinely dead blocks in the\ncrate's own source (excluding quoted Asciidoctor / AsciiDoc reference\nmaterial):\n\n- `passthroughs.rs`: an abandoned trailing-backslash truncation approach,\n superseded by the retry logic that follows it.\n- `sdd/src/main.rs`: a developer debugging shortcut that scoped file\n processing to a single file.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "chore: Remove commented-out dead code (close #705) (#870)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T14:09:52Z", "body_truncated": false, "is_coding_agent": true }, { "oid": "dbacb2413f412cdbee15fd2ebd8ff150b1c77b34", "body": null, "is_bot": false, "headline": "chore(asciidoc-parser): release v0.24.0 (#863)", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T04:33:53Z", "body_truncated": false, "is_coding_agent": false }, { "oid": "99cf75ffb9858f73cb164da754ce25058e314f13", "body": "…tle (#862)\n\nAdd a regression test asserting that a block attribute line above the\ndocument title whose value carries a `{counter:…}` reference does not fire\nthe counter at header time when the run is ultimately rejected (here by an\nembedded `[[anchor]]`).\n\n`document_title_follows_block_metadata` sc\n[…]\nparser and the counter advances exactly once. This\nlocks in that behavior, salvaging the one piece of unique coverage from the\nsuperseded #833.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "test: Cover counter deferral for a rejected metadata run above the ti…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T04:27:28Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "0944b66c0ba58ae3c2a2dc942f070698241756d1", "body": "…ub (#861)\n\nIssue #308 asked whether a block title can span multiple lines via a\ntrailing `+`. The answer is no: a title is a single line, and a trailing\n` +` is retained literally rather than joined to the following line\n(confirmed against the parser). Replace the stale `TO DO` comment linking\nto #\n[…]\n `to_do_verifies!` stub convention.\n\nThe `|Titles |{y}` spec-coverage marker stays; that gap is tracked by the\n`to_do_verifies!` sweep in #628.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "test: Remove resolved #308 reference from post_replacements titles st…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T04:07:15Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "adf9ff733355bea5b2dba6b52c30deb736ecbc0d", "body": "…9) (#852)\n\n* fix: Fuse legacy `+`-continued multi-line attribute values (close #729)\n\nAn attribute entry value can be continued across lines with a trailing\n` +` (legacy) as well as ` \\` (modern). Previously only the backslash\ncontinuation was fused; a legacy `+`-continued value was not joined — th\n[…]\nn the document body).\n\nAdds span-, fold-, and parse-level regression tests.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Fuse legacy `+`-continued multi-line attribute values (close #72…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T04:06:45Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "3f2e0d78c748fff27314a181285a2863f43d4b05", "body": "…732) (#850)\n\n* fix: Formal `role=` replaces roles set via shorthand `.role` (close #732)\n\nWhen merging multiple block attribute lines, roles now follow\nAsciidoctor's running model: a formal `role=` entry replaces every role\naccumulated so far, while shorthand `.role` entries append. Previously\nall \n[…]\nat\n the formal value replaces the running roles and the shorthand appends.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "fix: Formal `role=` replaces roles set via shorthand `.role` (close #…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T03:59:34Z", "body_truncated": true, "is_coding_agent": true }, { "oid": "cab8554693ddb8d05d68eb5dd37bdf05384d37ff", "body": "…lose #745) (#848)\n\n* feat: Drop YAML/TOML front matter when `skip-front-matter` is set (close #745)\n\nA `---`-fenced block at the very top of the document is now removed – and\nits content captured in the `front-matter` document attribute – when the\n`skip-front-matter` attribute is set, mirroring Asc\n[…]\n, `+++` TOML is not, and the content is\nstored verbatim rather than parsed.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com>", "is_bot": false, "headline": "feat: Drop YAML-style front matter when `skip-front-matter` is set (c…", "author_name": "Eric Scouten", "author_login": "scouten", "committed_at": "2026-07-23T03:54:47Z", "body_truncated": true, "is_coding_agent": true } ], "releases_count": 55, "commits_last_year": 546, "latest_release_at": "2026-08-01T16:14:24Z", "latest_release_tag": "v0.29.4", "releases_from_tags": false, "days_since_last_push": 0, "active_weeks_last_year": 37, "days_since_latest_release": 0, "mean_days_between_releases": 0.7 }, "community": { "has_readme": true, "has_license": true, "has_description": true, "has_contributing": false, "health_percentage": 37, "has_issue_template": false, "has_code_of_conduct": false, "has_pull_request_template": false }, "ecosystem": { "packages": [ { "name": "sdd", "exists": true, "license": "Apache-2.0", "keywords": [ "concurrent", "garbage", "memory", "epoch", "lock-free", "data-structures", "concurrency", "memory-management" ], "ecosystem": "crates", "matches_repo": false, "registry_url": "https://crates.io/crates/sdd", "is_deprecated": false, "latest_version": "4.8.8", "repository_url": "https://codeberg.org/wvwwvwwv/scalable-delayed-dealloc", "versions_count": 72, "total_downloads": 77608068, "dependents_count": null, "deprecation_note": null, "maintainers_count": null, "monthly_downloads": 5899173, "first_published_at": "2024-04-14T18:03:40.616625Z", "latest_published_at": "2026-07-02T14:12:15.625601Z", "latest_version_yanked": false, "days_since_latest_publish": 30 }, { "name": "asciidoc-parser", "exists": true, "license": "MIT OR Apache-2.0", "keywords": [ "parser", "asciidoc", "parser-implementations" ], "ecosystem": "crates", "matches_repo": true, "registry_url": "https://crates.io/crates/asciidoc-parser", "is_deprecated": false, "latest_version": "0.29.4", "repository_url": "https://github.com/asciidoc-rs/asciidoc-parser", "versions_count": 55, "total_downloads": 13542, "dependents_count": null, "deprecation_note": null, "maintainers_count": null, "monthly_downloads": 2012, "first_published_at": "2024-10-26T22:27:57.063155Z", "latest_published_at": "2026-08-01T16:14:20.394752Z", "latest_version_yanked": false, "days_since_latest_publish": 0 } ] }, "popularity": { "forks": 4, "stars": 34, "watchers": 2, "fork_history": { "days": [ { "date": "2026-01-23", "count": 1 }, { "date": "2026-02-17", "count": 1 }, { "date": "2026-04-01", "count": 1 }, { "date": "2026-07-18", "count": 1 } ], "complete": true, "collected": 4, "total_forks": 4 }, "star_history": null, "open_issues_and_prs": 5 }, "ai_readiness": { "has_nix": false, "example_dirs": [ "examples" ], "has_llms_txt": false, "has_dockerfile": false, "has_mcp_signal": false, "bootstrap_files": [], "api_schema_files": [], "has_devcontainer": true, "typecheck_configs": [], "toolchain_manifests": [ "Cargo.toml", "parser/Cargo.toml", "sdd/Cargo.toml" ], "largest_source_bytes": 434972, "source_files_sampled": 419, "oversized_source_files": 45, "agent_instruction_files": [], "agent_instruction_max_bytes": null }, "dependencies": { "manifests": [ "Cargo.toml", "parser/Cargo.toml", "sdd/Cargo.toml" ], "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": 10, "direct_affected_count": 0 }, "ecosystems": [ "crates" ], "dependencies": [ { "name": "bytecount", "manifest": "parser/Cargo.toml", "ecosystem": "crates", "version_constraint": "0.6.7" }, { "name": "memchr", "manifest": "parser/Cargo.toml", "ecosystem": "crates", "version_constraint": "2.6.4" }, { "name": "percent-encoding", "manifest": "parser/Cargo.toml", "ecosystem": "crates", "version_constraint": "2.3.2" }, { "name": "regex", "manifest": "parser/Cargo.toml", "ecosystem": "crates", "version_constraint": "1.11.1" }, { "name": "self_cell", "manifest": "parser/Cargo.toml", "ecosystem": "crates", "version_constraint": "1.2.0" }, { "name": "thiserror", "manifest": "parser/Cargo.toml", "ecosystem": "crates", "version_constraint": "2.0.1" }, { "name": "walkdir", "manifest": "sdd/Cargo.toml", "ecosystem": "crates", "version_constraint": "2.5" } ], "all_dependencies": { "error": null, "source": "github-sbom", "packages": [ { "name": "bytecount", "direct": true, "version": null, "ecosystem": "crates" }, { "name": "memchr", "direct": true, "version": null, "ecosystem": "crates" }, { "name": "percent-encoding", "direct": true, "version": null, "ecosystem": "crates" }, { "name": "regex", "direct": true, "version": null, "ecosystem": "crates" }, { "name": "self_cell", "direct": true, "version": null, "ecosystem": "crates" }, { "name": "thiserror", "direct": true, "version": null, "ecosystem": "crates" }, { "name": "walkdir", "direct": true, "version": null, "ecosystem": "crates" }, { "name": "codspeed-criterion-compat", "direct": false, "version": null, "ecosystem": "crates" }, { "name": "criterion", "direct": false, "version": null, "ecosystem": "crates" }, { "name": "pretty_assertions_sorted", "direct": false, "version": null, "ecosystem": "crates" } ], "collected": true, "truncated": false, "total_count": 10, "direct_count": 7, "indirect_count": 3 } }, "maintainership": { "issues": { "open_prs": 2, "merged_prs": 772, "open_issues": 3, "closed_ratio": 0.987, "closed_issues": 223, "closed_unmerged_prs": 40 }, "bus_factor": 2, "bot_contributors": 1, "top_contributors": [ { "type": "User", "login": "scouten", "commits": 759, "avatar_url": "https://avatars.githubusercontent.com/u/158391?v=4" }, { "type": "User", "login": "mojavelinux", "commits": 723, "avatar_url": "https://avatars.githubusercontent.com/u/79351?v=4" }, { "type": "User", "login": "graphitefriction", "commits": 37, "avatar_url": "https://avatars.githubusercontent.com/u/1124042?v=4" }, { "type": "User", "login": "ggrossetie", "commits": 3, "avatar_url": "https://avatars.githubusercontent.com/u/333276?v=4" }, { "type": "User", "login": "larryv", "commits": 2, "avatar_url": "https://avatars.githubusercontent.com/u/281175?v=4" }, { "type": "User", "login": "mmattel", "commits": 2, "avatar_url": "https://avatars.githubusercontent.com/u/3321281?v=4" }, { "type": "User", "login": "ahus1", "commits": 1, "avatar_url": "https://avatars.githubusercontent.com/u/3957921?v=4" }, { "type": "User", "login": "btat", "commits": 1, "avatar_url": "https://avatars.githubusercontent.com/u/1832069?v=4" }, { "type": "User", "login": "Vampire", "commits": 1, "avatar_url": "https://avatars.githubusercontent.com/u/325196?v=4" }, { "type": "User", "login": "danyill", "commits": 1, "avatar_url": "https://avatars.githubusercontent.com/u/674783?v=4" } ], "contributors_sampled": 22, "top_contributor_share": 0.492 }, "quality_signals": { "has_ci": true, "has_tests": true, "ci_workflows": [ "ci.yml", "pr_title.yml", "release.yml" ], "has_docs_dir": false, "linter_configs": [], "has_editorconfig": false, "has_linter_config": false, "has_precommit_config": false }, "security_signals": { "lockfiles": [], "scorecard": { "checks": [ { "name": "Binary-Artifacts", "score": 10, "reason": "no binaries found in the repo", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts" }, { "name": "Branch-Protection", "score": 3, "reason": "branch protection is not maximal on development and all release branches", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection" }, { "name": "CI-Tests", "score": 10, "reason": "30 out of 30 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 1/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 14 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": 10, "reason": "update tool detected", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool" }, { "name": "Fuzzing", "score": 0, "reason": "project is not fuzzed", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing" }, { "name": "License", "score": 10, "reason": "license file detected", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license" }, { "name": "Maintained", "score": 10, "reason": "30 commit(s) and 30 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": 10, "reason": "all dependencies are pinned", "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies" }, { "name": "SAST", "score": 0, "reason": "SAST tool is not run on all commits -- score normalized to 0", "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": "85320d8042ad10832b6e6cdc5cc7f7ef740c558f", "ran_at": "2026-08-01T18:21:44Z", "aggregate_score": 6.1, "scorecard_version": "v5.5.0" }, "has_codeql_workflow": false, "has_security_policy": false, "has_dependabot_config": true }, "contribution_flow": { "collected": true, "ci_last_run_at": "2026-08-01T17:56:39Z", "oldest_open_prs": [ { "number": 1039, "created_at": "2026-08-01T17:54:25Z", "last_comment_at": "2026-08-01T17:57:42Z", "last_comment_author": "codspeed-hq" }, { "number": 1040, "created_at": "2026-08-01T18:13:36Z", "last_comment_at": "2026-08-01T18:16:29Z", "last_comment_author": "codspeed-hq" } ], "last_merged_pr_at": "2026-08-01T17:53:45Z", "ci_last_conclusion": "SUCCESS", "oldest_open_issues": [ { "number": 943, "created_at": "2026-07-24T22:37:22Z", "last_comment_at": null, "last_comment_author": null }, { "number": 944, "created_at": "2026-07-24T22:37:43Z", "last_comment_at": null, "last_comment_author": null }, { "number": 1036, "created_at": "2026-08-01T17:29:43Z", "last_comment_at": null, "last_comment_author": null } ] } }, "config": { "disabled_metrics": [], "disabled_categories": [], "disabled_components": {} }, "source": { "url": "https://github.com/asciidoc-rs/asciidoc-parser", "host": "github.com", "name": "asciidoc-parser", "owner": "asciidoc-rs" }, "metrics": { "overall": { "key": "overall", "band": "good", "name": "Overall health", "note": "The weighted overall 66 is calibrated to 77 on the published index scale (record calibration 2026-08-02).", "notes": [ { "code": "overall_calibration", "params": { "raw": 66, "calibrated": 77, "calibration": "2026-08-02" } } ], "value": 77, "inputs": { "security": 61, "vitality": 94, "community": 43, "governance": 66, "calibration": "2026-08-02", "engineering": 61, "ai_readiness": 64, "weighted_overall_raw": 66 }, "components": [] }, "categories": [ { "key": "vitality", "band": "exceptional", "name": "Vitality", "value": 94, "weight": 0.21, "metrics": [ { "key": "development_activity", "band": "excellent", "name": "Development activity", "note": null, "notes": [], "value": 90, "inputs": { "commits_last_year": 546, "human_commit_share": 1, "days_since_last_push": 0, "active_weeks_last_year": 37 }, "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": "37/52 weeks with commits", "points": 25.6, "status": "partial", "details": [ { "code": "commit_cadence_weeks", "params": { "weeks": 37 } } ], "max_points": 36 }, { "key": "commit_volume", "name": "Commit volume", "detail": "546 commits in the last year", "points": 18, "status": "met", "details": [ { "code": "commits_last_year", "params": { "count": 546 } } ], "max_points": 18 }, { "key": "openssf_scorecard_maintained", "name": "OpenSSF Scorecard: Maintained", "detail": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10", "points": 10, "status": "met", "details": [], "max_points": 10 } ] }, { "key": "release_discipline", "band": "exceptional", "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": 100, "inputs": { "releases_count": 55, "latest_release_tag": "v0.29.4", "releases_from_tags": false, "days_since_latest_release": 0, "mean_days_between_releases": 0.7 }, "components": [ { "key": "ships_releases", "name": "Ships releases", "detail": "55 releases published", "points": 27, "status": "met", "details": [ { "code": "releases_published", "params": { "count": 55 } } ], "max_points": 27 }, { "key": "release_recency", "name": "Release recency", "detail": "latest release 0 days ago", "points": 36, "status": "met", "details": [ { "code": "release_recency", "params": { "days": 0 } } ], "max_points": 36 }, { "key": "release_cadence", "name": "Release cadence", "detail": "a release every ~0.7 days", "points": 27, "status": "met", "details": [ { "code": "release_cadence", "params": { "gap": 0.7 } } ], "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": "exceptional", "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": 3, "days_since_last_human_commit_is_floor": false }, "components": [ { "key": "project_is_still_maintained", "name": "Project is still maintained", "detail": "last human commit 3 days ago", "points": 100, "status": "met", "details": [ { "code": "abandonment_maintained", "params": { "days": 3 } } ], "max_points": 100 } ] } ], "description": "Is the project alive — is code being written and are releases shipping?" }, { "key": "community", "band": "weak", "name": "Community & Adoption", "value": 43, "weight": 0.17, "metrics": [ { "key": "popularity", "band": "at_risk", "name": "Popularity & adoption", "note": null, "notes": [], "value": 29, "inputs": { "forks": 4, "stars": 34, "watchers": 2, "growth_state": "unverified", "growth_factor_pct": 100, "growth_unverified_reason": "no_history" }, "components": [ { "key": "stars", "name": "Stars", "detail": "34 stars", "points": 24.6, "status": "partial", "details": [ { "code": "stars", "params": { "count": 34 } } ], "max_points": 60 }, { "key": "forks", "name": "Forks", "detail": "4 forks", "points": 4, "status": "partial", "details": [ { "code": "forks", "params": { "count": 4 } } ], "max_points": 25 }, { "key": "watchers", "name": "Watchers", "detail": "2 watchers", "points": 0, "status": "missed", "details": [ { "code": "watchers", "params": { "count": 2 } } ], "max_points": 15 } ] }, { "key": "community_health", "band": "moderate", "name": "Community health", "note": null, "notes": [], "value": 50, "inputs": { "has_readme": true, "has_license": true, "readme_badges": null, "has_contributing": false, "has_issue_template": false, "has_code_of_conduct": false, "readme_badge_services": [], "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 (Apache-2.0)", "points": 22.5, "status": "met", "details": [ { "code": "license_standard", "params": {} }, { "code": "license_spdx", "params": { "spdx": "Apache-2.0" } } ], "max_points": 22.5 }, { "key": "contributing_guide", "name": "CONTRIBUTING guide", "detail": null, "points": 0, "status": "missed", "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": "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": 55, "inputs": { "packages": [ "asciidoc-parser" ], "dependents": null, "ecosystems": "crates", "total_downloads": 13542, "monthly_downloads": 2012 }, "components": [ { "key": "monthly_downloads", "name": "Monthly downloads", "detail": "2,012 downloads/month across crates", "points": 44.1, "status": "partial", "details": [ { "code": "downloads_monthly", "params": { "count": 2012, "ecosystems": "crates" } } ], "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": "good", "name": "Sustainability & Governance", "value": 66, "weight": 0.23, "metrics": [ { "key": "maintainer_resilience", "band": "moderate", "name": "Maintainer resilience (bus factor)", "note": null, "notes": [], "value": 60, "inputs": { "bus_factor": 2, "contributors_sampled": 22, "top_contributor_share": 0.492 }, "components": [ { "key": "bus_factor", "name": "Bus factor", "detail": "2 contributor(s) cover half of all commits", "points": 25.2, "status": "partial", "details": [ { "code": "bus_factor", "params": { "count": 2 } } ], "max_points": 54 }, { "key": "commit_distribution", "name": "Commit distribution", "detail": "top contributor authored 49% of commits", "points": 11.4, "status": "partial", "details": [ { "code": "top_contributor_share", "params": { "share": 49 } } ], "max_points": 22.5 }, { "key": "contributor_breadth", "name": "Contributor breadth", "detail": "22 contributors", "points": 13.5, "status": "met", "details": [ { "code": "contributors_sampled", "params": { "count": 22 } } ], "max_points": 13.5 }, { "key": "openssf_scorecard_contributors", "name": "OpenSSF Scorecard: Contributors", "detail": "project has 14 contributing companies or organizations", "points": 10, "status": "met", "details": [], "max_points": 10 } ] }, { "key": "responsiveness", "band": "excellent", "name": "Issue & PR responsiveness", "note": "Excluded from scoring (no data or not applicable): Newcomer PR acceptance. Remaining weights renormalized.", "notes": [ { "code": "excluded_no_data", "params": { "components": [ "newcomer_pr_acceptance" ] } }, { "code": "weights_renormalized", "params": {} } ], "value": 80, "inputs": { "merged_prs": 772, "open_issues": 3, "closed_issues": 223, "prs_merged_7d": null, "prs_decided_7d": null, "prs_merged_30d": null, "prs_decided_30d": null, "issue_closed_ratio": 0.987, "closed_unmerged_prs": 40, "first_time_authors_30d": null, "first_time_prs_merged_30d": null, "first_time_prs_decided_30d": null }, "components": [ { "key": "issue_resolution", "name": "Issue resolution", "detail": "99% of issues closed", "points": 41.5, "status": "partial", "details": [ { "code": "issues_closed_share", "params": { "share": 99 } } ], "max_points": 42 }, { "key": "pr_acceptance", "name": "PR acceptance", "detail": "772/812 decided PRs merged", "points": 28.5, "status": "partial", "details": [ { "code": "decided_prs_merged", "params": { "merged": 772, "decided": 812 } } ], "max_points": 30 }, { "key": "newcomer_pr_acceptance", "name": "Newcomer PR acceptance", "detail": "no first-time contributor's PR decided in 30d", "points": 0, "status": "excluded", "details": [ { "code": "no_newcomer_prs", "params": { "days": 30 } } ], "max_points": 13 }, { "key": "openssf_scorecard_code_review", "name": "OpenSSF Scorecard: Code-Review", "detail": "Found 1/30 approved changesets -- score normalized to 0", "points": 0, "status": "missed", "details": [], "max_points": 15 } ] }, { "key": "stewardship", "band": "at_risk", "name": "Ownership & stewardship", "note": null, "notes": [], "value": 34, "inputs": { "followers": 0, "owner_type": "Organization", "is_verified": null, "owner_login": "asciidoc-rs", "public_repos": 2, "account_age_days": 175 }, "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": "0 followers of asciidoc-rs", "points": 0, "status": "missed", "details": [ { "code": "owner_followers", "params": { "count": 0, "login": "asciidoc-rs" } } ], "max_points": 25 }, { "key": "track_record", "name": "Track record", "detail": "2 public repos, account ~0 yr old", "points": 4.4, "status": "partial", "details": [ { "code": "public_repos", "params": { "count": 2 } }, { "code": "account_age_years", "params": { "years": 0 } } ], "max_points": 25 } ] }, { "key": "package_maintenance", "band": "exceptional", "name": "Package maintenance", "note": null, "notes": [], "value": 100, "inputs": { "packages": [ "asciidoc-parser" ], "ecosystems": "crates", "any_deprecated": false, "min_days_since_publish": 0 }, "components": [ { "key": "published_resolvable", "name": "Published & resolvable", "detail": "1 package(s) on crates", "points": 25, "status": "met", "details": [ { "code": "packages_published", "params": { "count": 1, "ecosystems": "crates" } } ], "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": "55 published versions", "points": 20, "status": "met", "details": [ { "code": "published_versions", "params": { "count": 55 } } ], "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": 61, "weight": 0.19, "metrics": [ { "key": "engineering_practices", "band": "good", "name": "Engineering practices", "note": null, "notes": [], "value": 68, "inputs": { "has_ci": true, "has_tests": true, "has_editorconfig": false, "has_linter_config": false, "has_precommit_config": false }, "components": [ { "key": "ci_workflows", "name": "CI workflows", "detail": "3 workflow(s)", "points": 24, "status": "met", "details": [ { "code": "ci_workflows", "params": { "count": 3 } } ], "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": null, "points": 0, "status": "missed", "details": [], "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": "30 out of 30 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": [ "asciidoc", "markup", "parser" ], "has_wiki": false, "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": "3 topics", "points": 10, "status": "met", "details": [ { "code": "topics_count", "params": { "count": 3 } } ], "max_points": 10 }, { "key": "wiki", "name": "Wiki", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 10 } ] } ], "description": "Are baseline engineering and documentation practices in place?" }, { "key": "security", "band": "moderate", "name": "Security", "value": 61, "weight": 0.16, "metrics": [ { "key": "security_posture", "band": "moderate", "name": "Security posture", "note": "Excluded from scoring (no data or not applicable): Signed-Releases. Remaining weights renormalized.", "notes": [ { "code": "excluded_no_data", "params": { "components": [ "signed_releases" ] } }, { "code": "weights_renormalized", "params": {} } ], "value": 61, "inputs": { "source": "openssf_scorecard", "checks_evaluated": 17, "scorecard_version": "v5.5.0", "checks_inconclusive": 1, "scorecard_aggregate": 6.1 }, "components": [ { "key": "binary_artifacts", "name": "Binary-Artifacts", "detail": "no binaries found in the repo", "points": 7.5, "status": "met", "details": [], "max_points": 7.5 }, { "key": "branch_protection", "name": "Branch-Protection", "detail": "branch protection is not maximal on development and all release branches", "points": 2.2, "status": "partial", "details": [], "max_points": 7.5 }, { "key": "ci_tests", "name": "CI-Tests", "detail": "30 out of 30 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 1/30 approved changesets -- score normalized to 0", "points": 0, "status": "missed", "details": [], "max_points": 7.5 }, { "key": "contributors", "name": "Contributors", "detail": "project has 14 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": "update tool detected", "points": 7.5, "status": "met", "details": [], "max_points": 7.5 }, { "key": "fuzzing", "name": "Fuzzing", "detail": "project is not fuzzed", "points": 0, "status": "missed", "details": [], "max_points": 5 }, { "key": "license", "name": "License", "detail": "license file detected", "points": 2.5, "status": "met", "details": [], "max_points": 2.5 }, { "key": "maintained", "name": "Maintained", "detail": "30 commit(s) and 30 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": "all dependencies are pinned", "points": 5, "status": "met", "details": [], "max_points": 5 }, { "key": "sast", "name": "SAST", "detail": "SAST tool is not run on all commits -- score normalized to 0", "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": "exceptional", "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" ], "commit_weight_rule": { "min_commits": 50, "min_commit_share": 0.1 }, "review_only_matches": 0, "below_threshold_exposures": [], "assessed_self_published_locations": 21 }, "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": 64, "weight": 0.04, "metrics": [ { "key": "ai_agent_context", "band": "weak", "name": "Agent context & guidance", "note": null, "notes": [], "value": 40, "inputs": { "has_llms_txt": false, "legible_history_share": 1, "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": "100 of 100 human commits state their intent (structured subject or explanatory body)", "points": 40, "status": "met", "details": [ { "code": "legible_history", "params": { "legible": 100, "sampled": 100 } } ], "max_points": 40 } ] }, { "key": "ai_verify_loop", "band": "excellent", "name": "Verify loop (build / test / typecheck)", "note": null, "notes": [], "value": 81, "inputs": { "has_nix": false, "has_tests": true, "lockfiles": [], "has_dockerfile": false, "typed_language": true, "bootstrap_files": [], "has_devcontainer": true, "has_linter_config": false, "typecheck_configs": [], "agent_commit_share": 0.86, "toolchain_manifests": [ "Cargo.toml", "parser/Cargo.toml", "sdd/Cargo.toml" ], "dependency_bot_commit_share": 0 }, "components": [ { "key": "one_command_bootstrap", "name": "One-command bootstrap", "detail": "Cargo.toml, parser/Cargo.toml, sdd/Cargo.toml (toolchain convention, no task runner)", "points": 12.6, "status": "partial", "details": [ { "code": "toolchain_convention", "params": { "files": "Cargo.toml, parser/Cargo.toml, sdd/Cargo.toml" } } ], "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": null, "points": 0, "status": "missed", "details": [], "max_points": 11 }, { "key": "static_type_checking", "name": "Static type checking", "detail": "Rust (statically typed)", "points": 11, "status": "met", "details": [ { "code": "statically_typed_language", "params": { "language": "Rust" } } ], "max_points": 11 }, { "key": "reproducible_environment", "name": "Reproducible environment", "detail": "devcontainer", "points": 10, "status": "met", "details": [ { "code": "file_list", "params": { "files": "devcontainer" } } ], "max_points": 10 }, { "key": "demonstrated_agent_practice", "name": "Demonstrated agent practice", "detail": "86 of the last 100 commits agent-authored or agent-credited", "points": 10, "status": "met", "details": [ { "code": "agent_authored_commits", "params": { "count": 86, "sampled": 100 } } ], "max_points": 10 }, { "key": "automated_maintenance", "name": "Automated maintenance", "detail": "dependency automation configured, none observed in the sampled commits", "points": 5, "status": "partial", "details": [ { "code": "dependency_bot_config_only", "params": {} } ], "max_points": 8 }, { "key": "openssf_scorecard_pinned_dependencies", "name": "OpenSSF Scorecard: Pinned-Dependencies", "detail": "all dependencies are pinned", "points": 10, "status": "met", "details": [], "max_points": 10 } ] }, { "key": "ai_code_legibility", "band": "exceptional", "name": "Code legibility for models", "note": null, "notes": [], "value": 94, "inputs": { "primary_language": "Rust", "largest_source_bytes": 434972, "source_files_sampled": 419, "oversized_source_files": 45 }, "components": [ { "key": "type_checkable_code", "name": "Type-checkable code", "detail": "Rust (statically typed)", "points": 45, "status": "met", "details": [ { "code": "statically_typed_language", "params": { "language": "Rust" } } ], "max_points": 45 }, { "key": "manageable_file_sizes", "name": "Manageable file sizes", "detail": "45/419 source files over 60KB", "points": 49.1, "status": "partial", "details": [ { "code": "oversized_source_files", "params": { "kb": 60, "sampled": 419, "oversized": 45 } } ], "max_points": 55 } ] }, { "key": "ai_interfaces", "band": "weak", "name": "Machine-readable interfaces", "note": null, "notes": [], "value": 40, "inputs": { "example_dirs": [ "examples" ], "has_mcp_signal": false, "api_schema_files": [] }, "components": [ { "key": "api_schema_openapi_graphql_proto", "name": "API schema (OpenAPI/GraphQL/proto)", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 40 }, { "key": "mcp_server", "name": "MCP server", "detail": null, "points": 0, "status": "missed", "details": [], "max_points": 20 }, { "key": "runnable_examples", "name": "Runnable examples", "detail": "examples", "points": 40, "status": "met", "details": [ { "code": "file_list", "params": { "files": "examples" } } ], "max_points": 40 } ] } ], "description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)." } ], "classification": { "top": [ "library" ], "labels": [ "library" ], "scores": { "library": 6 }, "primary": "library", "evidence": [ { "tier": "distribution", "label": "library", "source": "registry:crates", "weight": 6 } ], "artifacts": [], "confidence": "medium", "host_extension": false, "runs_as_process": false, "consumed_by_code": true }, "metrics_version": "2.5.0" }, "warnings": [ "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token", "crates package 'sdd' points at a different repository (https://codeberg.org/wvwwvwwv/scalable-delayed-dealloc); excluded from ecosystem scoring", "deps.dev does not index crates:asciidoc-parser@0.29.4; advisories assessed against the repository dependency graph instead", "No resolved dependencies carried a version and a supported ecosystem" ], "report_type": "repository", "generated_at": "2026-08-01T18:22:10.907697Z", "schema_version": "0.27.0", "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/a/asciidoc-rs/asciidoc-parser.svg", "full_name": "asciidoc-rs/asciidoc-parser", "license_state": "standard", "license_spdx": "Apache-2.0" }, "repoMeta": null, "notFound": false, "related": [ { "id": 36269, "full_name": "markedjs/marked", "url": "https://github.com/markedjs/marked", "description": "A markdown parser and compiler. Built for speed.", "ecosystem": "npm", "ecosystems": [ "npm" ], "primary_language": "JavaScript", "languages": [ "JavaScript", "TypeScript", "HTML" ], "topics": [ "markdown", "compiler", "parser", "commonmark", "gfm", "hacktoberfest", "markup", "html" ], "license_spdx": null, "license_state": "custom", "stars": 37026, "forks": 3613, "watchers": 381, "monthly_downloads": 242534193, "latest_score": 98, "latest_band": "exceptional", "latest_scanned_at": "2026-08-04T19:43:46.054715Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "maintained", "red_flags": [], "icon_url": "/icon/v1/markedjs/marked?v=6c02a7bf-1", "icon_source_type": "homepage", "badge_url": "" }, { "id": 9140, "full_name": "oxc-project/oxc", "url": "https://github.com/oxc-project/oxc", "description": "⚓ A collection of high-performance JavaScript tools.", "ecosystem": "crates", "ecosystems": [ "crates", "npm" ], "primary_language": "Rust", "languages": [ "Rust" ], "topics": [ "compiler", "javascript", "linter", "minifier", "parser", "typescript", "transpiler", "development-tools", "compilers", "web-programming" ], "license_spdx": "MIT", "license_state": "standard", "stars": 22220, "forks": 1171, "watchers": 85, "monthly_downloads": 1521396, "latest_score": 97, "latest_band": "exceptional", "latest_scanned_at": "2026-08-05T04:02:02.798361Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "maintained", "red_flags": [], "icon_url": "/icon/v1/oxc-project/oxc?v=de80ce08-1", "icon_source_type": "homepage", "badge_url": "" }, { "id": 18476, "full_name": "biomejs/biome", "url": "https://github.com/biomejs/biome", "description": "A toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.", "ecosystem": "crates", "ecosystems": [ "crates", "npm" ], "primary_language": "Rust", "languages": [ "Rust" ], "topics": [ "css", "formatter", "javascript", "jsx", "linter", "static-code-analysis", "typescript", "web", "json", "parser", "development-tools", "web-programming" ], "license_spdx": "Apache-2.0", "license_state": "standard", "stars": 25498, "forks": 1175, "watchers": 98, "monthly_downloads": 233173, "latest_score": 96, "latest_band": "exceptional", "latest_scanned_at": "2026-08-05T03:11:12.534840Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "maintained", "red_flags": [], "icon_url": "/icon/v1/biomejs/biome?v=bf585c67-1", "icon_source_type": "homepage", "badge_url": "" }, { "id": 3036, "full_name": "swc-project/swc", "url": "https://github.com/swc-project/swc", "description": "Rust-based platform for the Web", "ecosystem": "crates", "ecosystems": [ "crates" ], "primary_language": "Rust", "languages": [ "Rust" ], "topics": [ "ecmascript", "compiler", "rust", "javascript", "parser", "babel", "swc", "ecmascript-parser", "typescript", "typescript-compiler", "typescript-parser" ], "license_spdx": "Apache-2.0", "license_state": "standard", "stars": 34163, "forks": 1533, "watchers": 182, "monthly_downloads": 1246493, "latest_score": 96, "latest_band": "exceptional", "latest_scanned_at": "2026-08-05T01:26:43.411729Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "maintained", "red_flags": [], "icon_url": "/icon/v1/swc-project/swc?v=400c5222-1", "icon_source_type": "homepage", "badge_url": "" }, { "id": 44230, "full_name": "wasmerio/wasmer", "url": "https://github.com/wasmerio/wasmer", "description": "🚀 Fast, secure, lightweight containers based on WebAssembly", "ecosystem": "crates", "ecosystems": [ "crates" ], "primary_language": "Rust", "languages": [ "Rust" ], "topics": [ "webassembly", "wasm", "wasi", "emscripten", "rust", "windows", "macos", "linux", "wasmer", "wasix", "runtime", "vm", "cli", "command-line-interface", "api-bindings", "cache", "caching", "types", "data-structures", "no-std", "toml", "parser-implementations" ], "license_spdx": "MIT", "license_state": "standard", "stars": 20940, "forks": 989, "watchers": 194, "monthly_downloads": 727452, "latest_score": 96, "latest_band": "exceptional", "latest_scanned_at": "2026-08-05T04:21:24.420344Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "maintained", "red_flags": [], "icon_url": "/icon/v1/wasmerio/wasmer?v=bf05dcc7-1", "icon_source_type": "homepage", "badge_url": "" }, { "id": 1517, "full_name": "tree-sitter/tree-sitter", "url": "https://github.com/tree-sitter/tree-sitter", "description": "An incremental parsing system for programming tools", "ecosystem": "crates", "ecosystems": [ "crates" ], "primary_language": "Rust", "languages": [ "Rust", "C" ], "topics": [ "incremental", "parsing", "tree-sitter", "rust", "parser", "wasm", "external-ffi-bindings", "api-bindings", "text-editors" ], "license_spdx": "MIT", "license_state": "standard", "stars": 26539, "forks": 2797, "watchers": 284, "monthly_downloads": 3981552, "latest_score": 95, "latest_band": "exceptional", "latest_scanned_at": "2026-08-05T02:50:54.012090Z", "has_high_risk_jurisdiction_exposure": false, "has_malicious_dependency": false, "growth_authenticity": "unverified", "abandonment_state": "maintained", "red_flags": [], "icon_url": "/icon/v1/tree-sitter/tree-sitter?v=a07c055f-1", "icon_source_type": "avatar", "badge_url": "" } ] } }
Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 2.5.0 · 2026-08-01 18:22 UTC

asciidoc-rs / asciidoc-parser

AsciiDoc parser

Rust · RubyApache-2.0★ 34 estrellas⑂ 4 forksdesde dic 2023Ver en GitHub ↗
TipoBibliotecacómo se determina

asciidoc-rs/asciidoc-parser tiene un índice de salud de 77 sobre 100, lo que lo sitúa en la banda Bueno. Su puntuación más alta es Vitality (94/100) y la más baja, Community & Adoption (43/100). Se actualizó por última vez hoy. 2 personas concentran la mayor parte del trabajo reciente.

77
global / 100
Bueno

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala estandarizada de 1 a 100. El resultado global parte de su media ponderada, calibrada contra la distribución del registro público para que las bandas tengan significado percentil; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe un límite «En riesgo» de 34.

77
Excepcional93-100El nivel más alto del registro (≈ el 5% superior); cumple prácticamente todos los criterios evaluados
Excelente80-92Sólido en todos los frentes; carencias menores
Bueno65-79Saludable; carencias limitadas y manejables
Moderado50-64Aceptable con carencias notables; se recomienda revisión
Débil35-49Debilidades sustanciales en varias áreas
En riesgo20-34Debilidades significativas; su adopción exige cautela
Crítico1-19Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

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

El resultado global ponderado 66 se calibra a 77 en la escala publicada del índice (calibración del registro 2026-08-02).

Titularidad

Asciidoc in RustOrganización
0 seguidores2 repositorios públicosdesde feb 2026

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

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicaciónEtiquetas
crates.iosddapunta a otro repositorio; no se puntúa4.8.85.899.17372hace 30 díasconcurrentgarbagememoryepochlock-freedata-structuresconcurrencymemory-management
crates.ioasciidoc-parser0.29.4201255hace 0 díasparserasciidocparser-implementations

Métricas por categoría

Vitalidad

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

94Excepcional · 21% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
25.6/36Cadencia de commits — 37/52 semanas con commits
18/18Volumen de commits — 546 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year546
human_commit_share1
days_since_last_push0
active_weeks_last_year37
Cómo se puntúa
27/27Publica versiones — 55 versiones publicadas
36/36Recencia de las versiones — última versión hace 0 días
27/27Cadencia de publicación — una versión cada ~0,7 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count55
latest_release_tagv0.29.4
releases_from_tagsno
days_since_latest_release0
mean_days_between_releases0,7
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

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

43Débil · 17% del índice global
Cómo se puntúa
24.6/60Estrellas — 34 estrellas
4/25Forks — 4 forks
0/15Observadores — 2 observadores
Datos de entrada utilizados
forks4
stars34
watchers2
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (Apache-2.0)
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
readme_badges
has_contributingno
has_issue_templateno
has_code_of_conductno
readme_badge_services
has_pull_request_templateno
Cómo se puntúa
44.1/80Descargas mensuales — 2012 descargas/mes en crates
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packagesasciidoc-parser
dependents
ecosystemscrates
total_downloads13.542
monthly_downloads2012
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

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

66Bueno · 23% del índice global
Cómo se puntúa
25.2/54Factor bus — la mitad de los commits recae en 2 contribuyente(s)
11.4/22.5Distribución de commits — el principal contribuyente firma el 49% de los commits
13.5/13.5Amplitud de contribuyentes — 22 contribuyentes
10/10OpenSSF Scorecard: Contributors — project has 14 contributing companies or organizations
Datos de entrada utilizados
bus_factor2
contributors_sampled22
top_contributor_share0,492
Cómo se puntúa
41.5/42Resolución de issues — 99% de issues cerradas
28.5/30Aceptación de PR — 772/812 PR decididos fusionados
0/13Newcomer PR acceptance — ningún PR de un contribuyente primerizo decidido en 30 d
0/15OpenSSF Scorecard: Code-Review — Found 1/30 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs772
open_issues3
closed_issues223
prs_merged_7d
prs_decided_7d
prs_merged_30d
prs_decided_30d
issue_closed_ratio0,987
closed_unmerged_prs40
first_time_authors_30d
first_time_prs_merged_30d
first_time_prs_decided_30d
Excluidos de la puntuación (sin datos o no aplicable): newcomer_pr_acceptance. Los pesos restantes se han renormalizado.
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
0/25Alcance del propietario — 0 seguidores de asciidoc-rs
4.4/25Trayectoria — 2 repos públicos, cuenta de ~0 años
Datos de entrada utilizados
followers0
owner_typeOrganization
is_verified
owner_loginasciidoc-rs
public_repos2
account_age_days175
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en crates
35/35Recencia de publicación — última publicación hace 0 días
20/20Historial de versiones — 55 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesasciidoc-parser
ecosystemscrates
any_deprecatedno
min_days_since_publish0

Calidad de Ingeniería

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

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

Documentación

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

Seguridad

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

61Moderado · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 30 out of 30 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 1/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 14 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
7.5/7.5Maintained — 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
5/5Pinned-Dependencies — all dependencies are pinned
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — sin datos
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate6,1
Excluidos de la puntuación (sin datos o no aplicable): signed_releases. Los pesos restantes se han renormalizado.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Tiene un peso deliberadamente pequeño (4%): las herramientas para agentes son una señal real de mantenimiento, pero un repositorio sin ninguna puede alcanzar igualmente 100/100.

64Moderado · 4% del índice global
Cómo se puntúa
0/45Instrucciones para agentes — sin CLAUDE.md / AGENTS.md / reglas de editor
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 100 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
Cómo se puntúa
12.6/18Arranque con un solo comando — Cargo.toml, parser/Cargo.toml, sdd/Cargo.toml (convención del toolchain, sin ejecutor de tareas)
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — Rust (tipado estático)
10/10Entorno reproducible — devcontainer
10/10Práctica demostrada con agentes — 86 de los últimos 100 commits con autoría o crédito de agente
5/8Mantenimiento automatizado — automatización de dependencias configurada, no observada en los commits muestreados
10/10OpenSSF Scorecard: Pinned-Dependencies — all dependencies are pinned
Datos de entrada utilizados
has_nixno
has_tests
lockfiles
has_dockerfileno
typed_language
bootstrap_files
has_devcontainer
has_linter_configno
typecheck_configs
agent_commit_share0,86
toolchain_manifestsCargo.toml, parser/Cargo.toml, sdd/Cargo.toml
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Rust (tipado estático)
49.1/55Tamaños de archivo manejables — 45/419 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageRust
largest_source_bytes434.972
source_files_sampled419
oversized_source_files45
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
0/20Servidor MCP
40/40Ejemplos ejecutables — examples
Datos de entrada utilizados
example_dirsexamples
has_mcp_signalno
api_schema_files

Datos clave

34estrellas de GitHub
22contribuidores
546commits en los últimos 12 meses
0días desde el último push
55versiones publicadas
2factor bus
3issues abiertas
crates.ioecosistemas de paquetes

Advertencias de recopilación de datos

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • crates package 'sdd' points at a different repository (https://codeberg.org/wvwwvwwv/scalable-delayed-dealloc); excluded from ecosystem scoring
  • deps.dev does not index crates:asciidoc-parser@0.29.4; advisories assessed against the repository dependency graph instead
  • No resolved dependencies carried a version and a supported ecosystem

Más detalle

Historial de estrellas y forks 0 ★ / 4 ⇿
0Estrellas
4Forks
20Versiones

Cuándo se añadió cada estrella y fork, recopilado de GitHub y agrupado por día. El crecimiento acumulado se sitúa justo encima de las adiciones diarias que lo componen, de modo que ambos se leen en conjunto: la acumulación orgánica sostenida no se parece en nada a un pico abrupto y efímero. Cuando esa diferencia es medible, se informa como autenticidad del crecimiento.

1223344412026-012026-042026-07
Mayor 0Menor 9Parche 11
OpenSSF Scorecard 6.1 / 10
6.1agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).Scorecard v5.5.0 · 2026-08-01 18:21 UTC

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests30 out of 30 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 1/30 approved changesets -- score normalized to 0
10Contributorsproject has 14 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
10Pinned-Dependenciesall dependencies are pinned
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
n/dSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
Dependencias directas 7
RegistroPaqueteRestricción de versiónManifiesto
crates.iobytecount0.6.7parser/Cargo.toml
crates.iomemchr2.6.4parser/Cargo.toml
crates.iopercent-encoding2.3.2parser/Cargo.toml
crates.ioregex1.11.1parser/Cargo.toml
crates.ioself_cell1.2.0parser/Cargo.toml
crates.iothiserror2.0.1parser/Cargo.toml
crates.iowalkdir2.5sdd/Cargo.toml
Todas las dependencias 10

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

RegistroPaqueteVersiónRelación
crates.iobytecountdirecta
crates.iomemchrdirecta
crates.iopercent-encodingdirecta
crates.ioregexdirecta
crates.ioself_celldirecta
crates.iothiserrordirecta
crates.iowalkdirdirecta
crates.iocodspeed-criterion-compatindirecta
crates.iocriterionindirecta
crates.iopretty_assertions_sortedindirecta
Avisos de dependencias sin evaluar

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

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [
        "asciidoc",
        "markup",
        "parser"
      ],
      "is_fork": false,
      "size_kb": 10362,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Ruby": 1365426,
        "Rust": 9173981
      },
      "pushed_at": "2026-08-01T18:18:34Z",
      "created_at": "2023-12-08T22:28:07Z",
      "owner_type": "Organization",
      "updated_at": "2026-08-01T17:53:52Z",
      "description": "AsciiDoc parser",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "Rust",
      "significant_languages": [
        "Rust",
        "Ruby"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Asciidoc in Rust",
      "type": "Organization",
      "login": "asciidoc-rs",
      "company": null,
      "location": null,
      "followers": 0,
      "avatar_url": "https://avatars.githubusercontent.com/u/259974080?v=4",
      "created_at": "2026-02-06T23:44:44Z",
      "is_verified": null,
      "public_repos": 2,
      "account_age_days": 175
    },
    "license": {
      "state": "standard",
      "spdx_id": "Apache-2.0",
      "raw_spdx": "Apache-2.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.29.4",
          "kind": "patch",
          "published_at": "2026-08-01T16:14:24Z"
        },
        {
          "tag": "v0.29.3",
          "kind": "patch",
          "published_at": "2026-08-01T15:12:16Z"
        },
        {
          "tag": "v0.29.2",
          "kind": "patch",
          "published_at": "2026-08-01T03:07:56Z"
        },
        {
          "tag": "v0.29.1",
          "kind": "patch",
          "published_at": "2026-07-31T16:04:51Z"
        },
        {
          "tag": "v0.29.0",
          "kind": "minor",
          "published_at": "2026-07-30T11:59:36Z"
        },
        {
          "tag": "v0.28.1",
          "kind": "patch",
          "published_at": "2026-07-29T04:41:03Z"
        },
        {
          "tag": "v0.28.0",
          "kind": "minor",
          "published_at": "2026-07-29T01:56:13Z"
        },
        {
          "tag": "v0.27.4",
          "kind": "patch",
          "published_at": "2026-07-27T19:11:27Z"
        },
        {
          "tag": "v0.27.3",
          "kind": "patch",
          "published_at": "2026-07-27T14:34:35Z"
        },
        {
          "tag": "v0.27.2",
          "kind": "patch",
          "published_at": "2026-07-26T18:15:58Z"
        },
        {
          "tag": "v0.27.1",
          "kind": "patch",
          "published_at": "2026-07-25T20:45:30Z"
        },
        {
          "tag": "v0.27.0",
          "kind": "minor",
          "published_at": "2026-07-25T04:26:16Z"
        },
        {
          "tag": "v0.26.0",
          "kind": "minor",
          "published_at": "2026-07-24T15:53:14Z"
        },
        {
          "tag": "v0.25.0",
          "kind": "minor",
          "published_at": "2026-07-23T15:22:02Z"
        },
        {
          "tag": "v0.24.0",
          "kind": "minor",
          "published_at": "2026-07-23T04:34:34Z"
        },
        {
          "tag": "v0.23.4",
          "kind": "patch",
          "published_at": "2026-07-18T16:01:38Z"
        },
        {
          "tag": "v0.23.3",
          "kind": "patch",
          "published_at": "2026-07-16T03:42:30Z"
        },
        {
          "tag": "v0.23.2",
          "kind": "patch",
          "published_at": "2026-07-16T00:51:13Z"
        },
        {
          "tag": "v0.23.1",
          "kind": "patch",
          "published_at": "2026-07-15T04:54:15Z"
        },
        {
          "tag": "v0.23.0",
          "kind": "minor",
          "published_at": "2026-07-14T15:11:44Z"
        },
        {
          "tag": "v0.22.1",
          "kind": "patch",
          "published_at": "2026-07-13T04:20:21Z"
        },
        {
          "tag": "v0.22.0",
          "kind": "minor",
          "published_at": "2026-07-13T02:50:59Z"
        },
        {
          "tag": "v0.21.0",
          "kind": "minor",
          "published_at": "2026-07-12T16:06:19Z"
        },
        {
          "tag": "v0.20.0",
          "kind": "minor",
          "published_at": "2026-07-12T02:15:00Z"
        },
        {
          "tag": "v0.19.2",
          "kind": "patch",
          "published_at": "2026-07-11T16:10:24Z"
        },
        {
          "tag": "v0.19.1",
          "kind": "patch",
          "published_at": "2026-07-10T15:21:10Z"
        },
        {
          "tag": "v0.19.0",
          "kind": "minor",
          "published_at": "2026-07-05T04:01:37Z"
        },
        {
          "tag": "v0.18.0",
          "kind": "minor",
          "published_at": "2026-07-04T21:17:01Z"
        },
        {
          "tag": "v0.17.0",
          "kind": "minor",
          "published_at": "2026-06-30T13:52:23Z"
        },
        {
          "tag": "v0.16.0",
          "kind": "minor",
          "published_at": "2026-06-29T20:57:15Z"
        },
        {
          "tag": "v0.15.2",
          "kind": "patch",
          "published_at": "2026-06-29T14:39:19Z"
        },
        {
          "tag": "v0.15.1",
          "kind": "patch",
          "published_at": "2026-06-20T00:28:43Z"
        },
        {
          "tag": "v0.15.0",
          "kind": "minor",
          "published_at": "2026-06-19T01:21:07Z"
        },
        {
          "tag": "v0.14.5",
          "kind": "patch",
          "published_at": "2026-06-18T04:38:17Z"
        },
        {
          "tag": "v0.14.4",
          "kind": "patch",
          "published_at": "2026-03-07T16:38:47Z"
        },
        {
          "tag": "v0.14.3",
          "kind": "patch",
          "published_at": "2026-01-25T01:19:57Z"
        },
        {
          "tag": "v0.14.2",
          "kind": "patch",
          "published_at": "2026-01-17T20:00:18Z"
        },
        {
          "tag": "v0.14.1",
          "kind": "patch",
          "published_at": "2026-01-02T02:48:33Z"
        },
        {
          "tag": "v0.14.0",
          "kind": "minor",
          "published_at": "2025-12-08T04:33:46Z"
        },
        {
          "tag": "v0.13.1",
          "kind": "patch",
          "published_at": "2025-11-17T00:30:53Z"
        },
        {
          "tag": "v0.13.0",
          "kind": "minor",
          "published_at": "2025-11-16T02:12:01Z"
        },
        {
          "tag": "v0.12.0",
          "kind": "minor",
          "published_at": "2025-11-15T01:04:20Z"
        },
        {
          "tag": "v0.11.0",
          "kind": "minor",
          "published_at": "2025-11-02T21:47:12Z"
        },
        {
          "tag": "v0.10.0",
          "kind": "minor",
          "published_at": "2025-10-15T02:27:11Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2025-10-12T23:17:56Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2025-10-10T05:04:40Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2025-09-18T04:35:20Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2025-09-08T05:10:31Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2025-08-16T20:42:11Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2025-04-27T19:26:02Z"
        },
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2025-04-14T03:55:19Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2025-04-11T20:31:10Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2024-11-30T19:23:59Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2024-10-26T22:33:15Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2024-10-26T22:28:00Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "85320d8042ad10832b6e6cdc5cc7f7ef740c558f",
          "body": "A block title (`.Title`) directly above the `= …` document-title line\nmeans the line is not the document title. Asciidoctor demotes it to a\nlevel-0 section heading in the body, leaves the header empty, and logs\n\"level 0 sections can only be used when doctype is book\".\n\nv0.29.3 delivered only the car\n[…]\nning still hold. This also\nmakes a block title above `= …` at the document start behave exactly like\nthe same construct mid-body.\n\nCloses #1037\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Demote the document title when block metadata precedes it (#1038)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T17:53:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b658c8d3f19b02767dd0c0e447cb1eb9d99cfaca",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.29.4 (#1035)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T16:13:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ffb81e9641a3d6e2fa640752a81f796915ac46ca",
          "body": "…ue (#1034)\n\n* fix: Strip a trailing `@` soft-set modifier from an API attribute value\n\nA single trailing `@` on an attribute value supplied via the API (the\nAsciidoctor CLI/API soft-set modifier) is now stripped from the stored\nvalue, and the attribute is made overridable by a document `:name:` ent\n[…]\nhe crate's `#![deny(warnings)]`,\nfailing the internal-documentation CI job.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Strip a trailing `@` soft-set modifier from an API attribute val…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T16:06:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "78f8a5f0e76c29812d4ebef7263e363faf21bcc0",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.29.3 (#1031)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T15:11:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "42a8a285fe280f75443d82564a7a5de3fd064610",
          "body": "…try (#1032)\n\nA single `:author:` attribute entry populated `author` (and the derived\n`firstname`, `lastname`, `authorinitials`, …) inline but never set the\ncombined `authors` attribute, so `{authors}` rendered empty. The implicit\nauthor line and the `:authors:` / indexed `:author_N:` forms all set \n[…]\n is done inline rather\nthan through `set_author_metadata` so an explicit `:authorinitials:`\noverride on this path still survives.\n\nCloses #1027\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Set the combined `authors` attribute from a single `:author:` en…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T15:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e9d97bc5912e51fe49857cff17e1ab4c3cfaebf1",
          "body": "…ent (#1030)\n\n* fix: Treat a section heading inside a delimited block as literal content\n\nA `== …` line inside a delimited block (an example `====`, sidebar\n`****`, or open `--` block, a quote `____` block, or a Markdown-style\nblockquote) was parsed as a real section. Asciidoctor only recognizes\nsec\n[…]\nary, so cell sections are recognized\nregardless of where the table appears.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Treat a section heading inside a delimited block as literal cont…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T05:04:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0c5621ec0f21620d893fe4192b4959fdc30b04fc",
          "body": "…le (#1028)\n\n* fix: Coerce a leveloffset-shifted level-0 heading to the document title\n\nWhen a `:leveloffset:` shift drives a heading to effective level 0, that\nheading is now coerced to the document title (doctitle), mirroring\nAsciidoctor's `is_next_line_doctitle?`. Previously the offset was applie\n[…]\nvel-1 section by the body parser. Add a test for\nthe tab-delimited variant.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Coerce a leveloffset-shifted level-0 heading to the document tit…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T04:07:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "761ebf78f9ee3f31e795c4b28f076f1d69b03e04",
          "body": "…rally (#1026)\n\n* fix: Ignore an empty block anchor `[[]]` instead of rendering it literally\n\nAn empty bracketed block anchor (`[[]]`) on its own line above a block\nnames nothing. Asciidoctor drops it; this crate was instead leaving the\nline in place, so it rendered as a literal `[[]]` paragraph bef\n[…]\n\nblock\". Adds regression tests for both the open-block and lone-body forms.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Ignore an empty block anchor `[[]]` instead of rendering it lite…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T04:00:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e271a290c583a186e10746842cf1da59511c2a3e",
          "body": "…adata (#1029)\n\nA block title line (`.Title`) directly above the document title (`= …`)\nwas not recognized in the document header. It fell through to the block\nparser, which attached the block title to a paragraph whose text was the\nescaped `= …` line, so the title was rendered as literal paragraph \n[…]\ncument title as a level-0 section, so it keeps `= …` as the\ndocument title. The block-title recognition and carryover are shared.\n\nCloses #1022\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Recognize a block title above the document title as document met…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T03:44:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0f9585ba016d1ff540d1d9c9574596be7dd5f66a",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.29.2 (#1019)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T03:07:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c50dc8ee7b4013ff083fa029389485ec1cc93497",
          "body": "… include (#1021)\n\nAn `IncludeFileHandler` that finds and reads a file which is not valid UTF-8\nand cannot be transcoded (no `encoding` attribute, or one it does not support)\npreviously had to return `IncludeResolution::NotFound`, misreporting the cause\nas \"include file not found\".\n\nAdd an `IncludeR\n[…]\ntor's fatal\n`invalid byte sequence in UTF-8` does.\n\nBoth types are `#[non_exhaustive]`, so the additions are backward compatible.\n\nCloses #1020\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: Add IncludeResolution::NotDecodable for a found-but-undecodable…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T03:03:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1d7839bdd1d89446284ec87256f5b36ca56bcbee",
          "body": "…tains a nested section (#1017)\n\n* fix: Emit a warning when a special section that doesn't support subsections contains a nested section\n\nSpecial sections such as `glossary`, `bibliography`, `colophon`,\n`dedication`, and `index` do not support nested sections. Asciidoctor\nlogs an error (e.g. `glossa\n[…]\ntion. Adds a regression\ntest covering metadata above the offending heading.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Warn when a special section that doesn't support subsections con…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T02:52:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bca694ba89c7379d20d85c637ff74cfcc8b9e1d6",
          "body": "…te heading (#1018)\n\n* fix: Treat a `[float]`/`[discrete]` level-0 (`=`) heading as a discrete heading\n\nA `[float]`/`[discrete]` style on a level-0 (`=`) heading was promoted to\nthe document title and dropped from the block stream, instead of yielding a\ndiscrete floating-title block. Discrete headin\n[…]\nstyles_gate_doctitle_by_effective_style` covering both\noverride directions.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Treat a `[float]`/`[discrete]` level-0 (`=`) heading as a discre…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T02:47:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c603302bcfad4510b3a679cf89ff8da3ff091b8a",
          "body": "…tring (#1016)\n\nWhen an indexed `:author_N:` attribute entry overrode one author of a\nmulti-author implicit author line, the individual `author_N` attribute was\nupdated but the combined `authors` string (and `Document::authors()`) still\nreflected the original, un-overridden author.\n\n`resolve_authors\n[…]\nluding `authors` and `authorcount` –\nso `{authors}`, `Document::authors()`, and the resolved author list all\nreflect the override.\n\nclose #1013\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Reflect an indexed :author_N: override in the combined authors s…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-08-01T02:28:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e89e7584b1fcb5e57c26f93cfb2c19db6795908c",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.29.1 (#1010)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-31T16:04:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e4a74f7f3a1577667e4799d3375967953dcbd9c3",
          "body": "…artitioning (#1009)\n\n* fix: Run :author: attribute value through substitutions before name partitioning\n\nAsciidoctor substitutes an attribute-entry value (via\napply_attribute_value_subs) before process_authors partitions it into name\nparts. Two gaps caused asciidoc-parser to partition the raw, unsu\n[…]\n test documenting\nthis so the behavior is not mistaken for a dropped email.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Run :author: attribute value through substitutions before name p…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-31T16:00:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "02f4349b53e3db823a69cd0f17901d36cb49ac8a",
          "body": "…-line (#1012)\n\n* fix: Emit a diagnostic for each line dropped under attribute-missing=drop-line\n\nWhen `attribute-missing` is set to `drop-line`, the parser correctly drops\nthe offending line (or blanks a header attribute value), but until now it\nrecorded no diagnostic, so a caller had no way to obs\n[…]\nion. Adds a\nregression test parsing `['{missing}']++x++` under `drop-line`.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Emit a diagnostic for lines dropped under attribute-missing=drop…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-31T15:55:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b90ac8ae62f5ecb447c4ec19f32cb14d1a4a969e",
          "body": "…mplicit author line (#1007)\n\n* fix: Populate combined `authors` and `author_1` attributes from the implicit author line\n\nFor an implicit author line, Asciidoctor exposes a combined, comma-joined\n`authors` attribute and, when more than one author is present, the first\nauthor's attributes under both \n[…]\nts\nthe header-metadata hash cardinality, which this crate does not surface.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Populate combined `authors` and `author_1` attributes from the i…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-31T15:26:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "58f6b79043c04bec341acf4a0b75cd60f370fa19",
          "body": "…hor line (#1006)\n\n* fix: Reconcile an explicit `:authors:` entry against the implicit author line\n\nWhen an explicit `:authors:` attribute entry follows an implicit author\nline, Asciidoctor reconciles the two: if the entry's value does not match\nthe computed (comma-joined) value of the implicit list\n[…]\nfail loudly rather than silently\ndiverge from the reference implementation.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Reconcile an explicit `:authors:` entry against the implicit aut…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-31T14:23:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4fec22bf196eb4301d38061c9b461c2b267e45a2",
          "body": "…#1008)\n\nSurface the inline passthroughs (`+++…+++`, `++…++`, `$$…$$`, `pass:[…]`,\ninline STEM macros) that the substitution pipeline extracts from a block's\ncontent, so downstream consumers can assert – for each extracted\npassthrough – its stored (unescaped) text and its resolved substitution\nlist,\n[…]\nbs()`. `SubstitutionGroup::steps()` is now public too, so\nthe resolved, ordered substitution steps for an entry are inspectable.\n\nCloses #1002.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: Expose the inline passthrough collection on a block's content (…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-31T04:34:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6996bed96d60c872081c8efd442906613462d0ce",
          "body": "* chore(asciidoc-parser): release v0.29.0\n\n* docs(changelog): describe the #999 breaking change and migration for v0.29.0\n\nAdd a \"Breaking changes\" section to the 0.29.0 entry explaining the\nIncludeFileHandler::resolve_target reshape (Option<IncludeContent> ->\nIncludeResolution) and how to migrate a handler, matching the prose\nstyle used for earlier breaking releases.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.29.0 (#1001)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-30T11:58:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1059e9b9204bfa72649ee9ca7fc463c8fa2f2763",
          "body": "…(#1000)\n\nThe release_commits regex required the commit type to be immediately\nfollowed by `(` or `:`, so a scopeless breaking-change commit such as\n`feat!:` did not match. This meant release-plz reported \"no commit\nmatches the release commit regex\" and skipped opening a release PR\nafter #999.\n\nAdd an optional `!` before the `(`/`:` so all Conventional Commit\nforms – including `feat!:` and `fix!:` – trigger a release.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Match breaking-change commits (feat!:) in release_commits regex …",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-30T11:51:23Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8a274b3472c985f8d83a9659eb0c843307e16d09",
          "body": "* feat!: Distinguish an unreadable include file from a missing one\n\nWhen an `include::` directive names a file that exists but cannot be\nread (e.g. a permission error), the parser previously reported it\nidentically to a missing file (`WarningType::IncludeFileNotFound`).\nAsciidoctor distinguishes the\n[…]\nes a compile error here rather than silently collapsing into\n  \"not found\".\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat!: Distinguish an unreadable include file from a missing one (#999)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-30T05:09:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bf90b2983c3c11bdd3438cae3c2395697d075e98",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.28.1 (#997)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-29T04:40:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2fa904e123ffb8ceb69df3c74021f8eeed663d87",
          "body": "…it (#996)\n\n* fix: Keep block metadata attached when a comment sits directly above it\n\nA single-line comment (`//`) placed directly above a block-metadata line\n(an attribute list `[...]`, an anchor `[[...]]`, etc.) with no blank line\nbetween them detached that metadata from the block it decorated: t\n[…]\nary text directly above it already\nis, producing identical rendered output.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Keep block metadata attached when a comment sits directly above …",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-29T04:35:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2d066e138e2a784193f5962855272b8ea675dd3b",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.28.0 (#994)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-29T01:55:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2fd07c7e30a42627a85fad890feab0c4a7df08fe",
          "body": "* fix: Mirror Asciidoctor TOC position normalization\n\nResolve the `toc` family of attributes the way Asciidoctor's header\nnormalization does (`document.rb`), so the derived `toc-position` /\n`toc-placement` / `toc-class` attributes match for three inputs that\npreviously diverged:\n\n- direction shortha\n[…]\nnd\nadd a regression test covering `^`/`v`/`top`/`bottom`/`<`/`>` in a cell.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Mirror Asciidoctor TOC position normalization (#993)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-29T01:50:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9635c779449ff6a114f046eb05f8a65c30919282",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.27.4 (#991)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T19:10:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "64f2b3cbe2dc2509fc0836be9053cc96311cd84b",
          "body": "…(#990)\n\nAn API/intrinsic `numbered` attribute (`ModificationContext::ApiOnly`, as the\nhtml5 converter applies `attributes: { 'numbered' => '' }`) remapped to a\n*locked* `sectnums`, and a locked `sectnums` could not be unset by a body\n`:numbered!:` — so every section rendered numbered and the mid-do\n[…]\nPI`) from `non_normative!` to verified tests, and add\nfocused parser unit tests for both directions of the flexible-attribute lock.\n\nclose #989\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Unlock an API-enabled `numbered` so a body toggle still applies …",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T19:06:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c058b485333393e38211ed677dda13eb6b043e00",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.27.3 (#982)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T14:33:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8a59d4c7ae7753854ab89cc8b2f7e487c16c631f",
          "body": "Asciidoctor's `InlinePassRx` consumes one character before each inline\npassthrough it matches (its leading group absorbs the preceding\ncharacter and re-emits it). Because Ruby's `gsub` resumes scanning after\neach match, this shifts where the opening `+` lands inside a long run of\n`+` characters, par\n[…]\ntheir zero-width\nboundary. The retry path now splits on a char boundary since the\nconsumed preceding character may be multi-byte.\n\nCloses #979.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Tokenize a run of `+` around a passthrough like Asciidoctor (#988)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T14:30:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6e8550843e97f66d3060ed39e4c0306a5541b659",
          "body": "* fix: Preserve a quoted role on an inline passthrough span (#973)\n\nAn inline passthrough (or inline quoted text) whose role is enclosed in\nquotes – e.g. `['role']++text++` – dropped the role and rendered no\n`<span>`, diverging from Asciidoctor which keeps the quoted role verbatim.\n\nThe general attr\n[…]\nAsciidoctor slices at the\nfirst comma) with a unit assertion.\n\nCloses #987.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Preserve a quoted role on an inline passthrough span (#973) (#978)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T03:47:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "25fcab7ddb6a76043e5d9cd4661b32b006772692",
          "body": "…s caption (#984)\n\n* fix: Honor an empty document `caption` attribute to suppress a block's caption\n\nA document-wide `caption` attribute that is set but empty (bare `:caption:`,\nor `:caption:` with an empty value) now suppresses a captionable block's\ncaption and consumes no counter, matching Asciido\n[…]\n to\nsuch a block falls back to the block title, never a numbered signifier.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Honor an empty document `caption` attribute to suppress a block'…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T03:18:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5c4f74095a5e626626b6bf5d3b145963c49b432c",
          "body": "… mode (#985)\n\n* fix: Fall back to link macro for remote include under non-secure safe mode\n\nUnder a non-secure safe mode (`unsafe`/`safe`/`server`), a remote (URI)\n`include::` target whose `allow-uri-read` attribute is unset is a no-fetch\ncase: no network read is required, only that the target be *\n[…]\nes and\nall) as its `href`, rather than leaving `pass:c` as the destination.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Fall back to link macro for remote include under non-secure safe…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T03:17:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "95d31782df361c5ba32de2cbb5a78dba6885a0cf",
          "body": "* fix: Parse the `toc::[]` block macro as a `toc`-context block\n\nThe `toc::[]` block macro previously parsed as an ordinary paragraph\nwhose content was the literal text `toc::[]`, so a backend had no way to\ndetect the macro and render a table of contents at that position.\n\nAdd a `TocBlock` type (and\n[…]\nrget requirement into the `[` prefix check, removing an\nunreachable branch.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Parse the `toc::[]` block macro as a `toc`-context block (#986)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T03:10:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ef44687753e612ed06b8b8defcdfc836beb543c2",
          "body": "* feat: Expose an AsciiDoc table cell's own footnotes\n\nAn AsciiDoc (`a`) table cell is a nested document with its own footnote\nregistry, isolated from the main document (#544). That per-cell footnote\nlist was discarded after the cell parsed, so a renderer had no data to\nbuild the cell-local `#footno\n[…]\nop the issue reference, so no closed-issue link is\nleft behind in the code.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: Expose an AsciiDoc table cell's own footnotes (#977)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T02:58:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e378c1bbdeda984ad62380ae8cb81500e0633fc8",
          "body": "…ks (#976)\n\nAn externally-supplied `hardbreaks` attribute (Asciidoctor's `-a hardbreaks`\n/ `attributes: { 'hardbreaks' => '' }`) did not insert a `<br>` at each\nunwrapped paragraph line, even though the same attribute set as a header\nentry (`:hardbreaks:`) or a `[%hardbreaks]` block option did.\n\nAsc\n[…]\ntutions_test` hardbreaks cases now faithfully\nuse the API attribute (as upstream does) instead of sidestepping via\n`[%hardbreaks]`.\n\nclose #974\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Honor API-supplied `hardbreaks` document attribute for line brea…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-27T02:30:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "30d60ceedd4cda1f7e52986892dfaeb656bbf7fb",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.27.2 (#971)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-26T18:15:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "151472d4b863cd82f7c1f6ccc5df57cbfc7739f7",
          "body": "…8) (#970)\n\n* fix: Resolve cross-reference to the document title to its title text\n\nA cross-reference to a document title carrying an explicit shorthand ID\n(`[#id]` above `= Title`) rendered the bracketed `[id]` fallback instead\nof the title's reference text, because the document title was never\nreg\n[…]\n ends the header, and\nthe empty `[[]]` form remains rejected.\n\nCloses #968.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Resolve cross-references to the document title (issues #965, #96…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-26T18:03:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a036061fdaa93e10bb07f518ba70b8d722366dae",
          "body": "A discrete (floating) heading — a `[float]` or `[discrete]` styled title —\nwas exposed with the block context `section`, indistinguishable from an\nordinary section by context alone. Asciidoctor models it as a block whose\ncontext is `floating_title`, which consumers rely on to (for example)\nexclude d\n[…]\n\ntype is `Discrete`, and `section` otherwise. `resolved_context` follows,\nsince neither the `float` nor `discrete` style is a built-in context.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Report `floating_title` context for discrete headings (#967)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-26T17:49:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0cfe8b98bf6136c297dd888477298b2b8decc0c3",
          "body": "…(#969)\n\nThe newest `dtolnay/rust-toolchain` (master) makes the `toolchain` input\nrequired and no longer falls back to a default. Dependabot (#964) bumped\nevery pinned SHA – including the ones tagged `# stable` and `# nightly` –\nto the single master SHA, so the jobs that relied on a tag's built-in\nd\n[…]\nss an explicit `toolchain:`\ninput so the setup is correct and stays clean under future Dependabot\nbumps (a single SHA to update).\n\nCloses #964.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci: Add required `toolchain` input for dtolnay/rust-toolchain (#964) …",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-26T17:42:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a288f6551831c319537370b60e507f2f1e3b235f",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.27.1 (#959)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T20:44:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "32dd76cdbcc6365ac4bf60ddb23cf87a3d388951",
          "body": "* fix: Unescape `\\{` and `\\}` in attribute reference substitution\n\nAn escaped attribute-reference brace should render as a literal brace with\nthe escaping backslash removed and the reference left unexpanded. The\nattribute-reference regex only recognized a backslash before the opening\nbrace (`\\{name}\n[…]\nan `{name}` form unexpanded, consistent with the\ncontent-substitution path.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Unescape `\\{` and `\\}` in attribute reference substitution (#963)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T20:41:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d48de8394a07d38a2f01965dee28babc4599fd6b",
          "body": "Remove the author_association (OWNER/COLLABORATOR/MEMBER) and explicit\ndependabot login checks from every job gate, relying purely on write\naccess to the primary repo via head.repo.full_name == github.repository.\nPushing a branch here already requires write access, so this covers\nmaintainers, dependabot, and agent-authored PRs alike. Fork PRs still\nawait the \"safe to test\" label.\n\nMirrors asciidoc-rs/asciidoc-html5#107.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: Rely on write access instead of author_association gates (#960)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T16:01:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2afd0b3a2b98bf8ad7630a4f9ca45d7849b5e48d",
          "body": "A block title whose first character is a period and is not followed by a\nspace (e.g. `..gitignore`) is now parsed as a block title with text\n`.gitignore`, matching Asciidoctor's `BlockTitleRx`\n(`^\\.(\\.?[^ \\t.]…)$`). Previously any line beginning with `..` was\nrejected as a title, so the marker line became a paragraph and the\nfollowing block lost its title.\n\nCloses #957\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Recognize block title with a leading period (`..name`) (#958)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T15:51:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "320ce4bdfac06a8ba4b9a1e1c684c0587ee43276",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.27.0 (#941)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T04:25:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aa767ff5cde506e86b4361ababa6c0266d9c44ac",
          "body": "* fix: capture block metadata on list items instead of dropping it\n\n`ListBlock::parse` built each list item with an empty `BlockMetadata`, so a\ntitle, anchor, or attribute list written directly before a list item's marker\nwas silently discarded. Worse, because the empty metadata could not parse past\n[…]\nt for them, restoring the original fast path for\nthe common paragraph case.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Capture block metadata on list items instead of dropping it (#954)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T04:22:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c4c7294195664e7d3005c7cc48796c9a2fdc9fcd",
          "body": "* chore: Pin GitHub Actions to specific commit SHAs\n\nReplace mutable version tags with pinned commit SHAs (each with a\ntrailing version comment) across ci.yml and pr_title.yml, following the\npattern already used in release.yml. Each SHA is the commit its tag or\nbranch currently resolves to. This har\n[…]\n currently resolves to) so all\nthree workflows share a single checkout SHA.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: Pin GitHub Actions to specific commit SHAs (#955)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T04:04:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b34f99e95e10c41ff93d4c26edf3ae455560998c",
          "body": "Part of the #939 TEMPORARY-marker audit. The `#[allow(...)]` attributes\nguarding test scaffolding are no longer warranted:\n\n- `assert_dom/virtual_dom.rs`: the `VirtualNode` builder helpers are now\n  used throughout the DOM assertions, so the blanket `#[allow(dead_code)]`\n  on the impl block is remov\n[…]\nunconstructed, so per the audit guidance they (and their\n  `Debug` / equality arms) are removed rather than left behind an allow.\n\nCloses #949.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: Remove consumed 'while building' scaffolding allows (#949) (#952)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T03:42:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8944d9105400fdba9e9d7fa29d266ad1ecf38818",
          "body": "…o_name (#953)\n\n`Span::take_ident` borrowed Rust's identifier definition (leading\nalphabetic/underscore, then alphanumerics/underscores) because\n\"identifier\" is not crisply defined in the AsciiDoc documentation. Its\nuse was already discouraged in favor of more specific helpers.\n\nThere was a single c\n[…]\nng digit) is now parsed and then rejected as unrecognized\nrather than rejected at the name-capture stage, with identical results.\n\nCloses #948.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: Replace Span::take_ident with spec-grounded take_block_macr…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T03:40:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "78d9373b0f7d80bbd965d48ec60c5924b6592832",
          "body": "…947) (#951)\n\nThe `Block` enum's variants have converged in size as the parser\nevolved. The two largest, `Section` (568 bytes) and `Media` (536\nbytes), now differ by only 32 bytes – far under clippy's 200-byte\n`large_enum_variant` threshold – so the lint no longer fires. The\n`#[allow]` (carried forw\n[…]\nasoning already\ndocumented on `BlockParseOutcome`).\n\nVerified with the CI invocation\n`cargo clippy --all-features --all-targets -- -Dwarnings`.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: Drop stale allow(clippy::large_enum_variant) on Block (close #…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T03:40:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "19faf3b5696dfb32a0f875f4d95ddb93db7a8706",
          "body": "Audit the code base for TEMPORARY / \"while building\" markers (excluding\n`ref` and tests quoting `ref` content) and convert the genuine ones to\nTODO comments that link to tracking issues, per #939.\n\n- List items discard block metadata (#946).\n- `Block` enum trips `clippy::large_enum_variant` (#947).\n- `Span::take_ident` uses a provisional identifier definition (#948).\n- Remove \"while building\" scaffolding allows once consumed (#949).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: replace TEMPORARY markers with issue-linked TODOs (#950)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-25T03:19:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5fdf0f42b24c7d41e72c1df86811d1789cd3eaba",
          "body": "Code-coverage review for dead code found no removable dead code: line\ncoverage is 98.79% and the compiler's dead_code lint is clean. The\nuncovered product lines are all intentional guardrails (defensive\nbranches, assertions, Debug impls, and a refactor-blocked region).\n\nThe one actionable cleanup is this stale attribute: the re-export is now\nused via crate::document::DuplicateIdError in the parser, so the\nallow(unused) suppresses nothing.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: Remove stale allow(unused) on DuplicateIdError re-export (#945)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T23:05:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4bbb8fe9f0018185442bda7a16e44b199f8a8e60",
          "body": "…haustive (#940)\n\n* feat: Derive Hash on the public AST / output types\n\nSpan, Block, Content, WarningType and the types reachable from them now\nimplement Hash, so blocks and spans can key a HashMap/HashSet and warnings can\nbe bucketed by type. ResolvedAttributes hashes an order-independent summary o\n[…]\nleValue / ModificationContext fields, all of which hold only Hashable\ndata.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: Derive Hash on the public AST/output types; mark Warning non_ex…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T21:39:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a59f603280d80c729d8a0f80afdb3554901d187b",
          "body": "…pat 5.0.0 -> 5.0.1 (#938)\n\nPatch-level updates to the benchmark harness dev-dependencies. Raising the\ndeclared floors keeps the -Z direct-minimal-versions CI job on the current\npatch releases. Benchmarks compile and minimal-versions resolves cleanly.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(deps): Bump criterion 0.8.0 -> 0.8.2 and codspeed-criterion-com…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T19:03:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ca8db26179c0fe77d71e8e55b3a358fde32945af",
          "body": "* chore(asciidoc-parser): release v0.26.0\n\n* docs: Add 0.26.0 breaking changes guide to the changelog\n\nDocument the source-level migration for the four breaking changes in\n0.26.0 (block traversal #930, PathResolver-as-trait #934, rendering API\npolish #929, and the SourceMap reshape #917), mirroring the prose\nguide added for 0.23.0.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.26.0 (#916)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T15:52:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "50f68b5578c980dbfe90d73256b5b3e3e8b27f97",
          "body": "…ers (close #896) (#933)\n\n* feat: Let a custom InlineSubstitutionRenderer override only what differs (close #896)\n\nTwo changes unblock a downstream (e.g. Zola) `InlineSubstitutionRenderer`:\n\n- Give every `InlineSubstitutionRenderer` method a default body that\n  delegates to the built-in `HtmlSubstit\n[…]\n is not surprised that `render_icon` and a direct `icon_uri`\ncall disagree.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: Let a custom InlineSubstitutionRenderer override only what diff…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T15:42:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "104ed44bd5ba50724bb852dbc58f9d423dcb9105",
          "body": "Warnings were deterministic but assembled by category (header, blocks,\npreprocessor, substitution, post-parse checks, then reference-resolution\nwarnings appended last), so an unresolved `include::` on an early line\ncould sort after a malformed inline macro further down, and unresolved-xref\nwarnings \n[…]\ne parse and after\na reference-resolution sweep folds its warnings in, so `warnings()` now\nyields line-ordered, still-deterministic diagnostics.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Emit document warnings in source order (close #901) (#932)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T15:06:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0202092e25f780df3441880c100fca1f2ed8082b",
          "body": "…(#936)\n\nPRs #930 (child_blocks API) and #934 (PathResolver trait) landed\nconcurrently without a rebase, leaving the with_path_resolver test\ncalling the removed Document::nested_blocks(). Point it at\nchild_blocks() to match the sibling call sites.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Repair stale nested_blocks() call left by concurrent PR landing …",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T14:36:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e454b6e3c8507d1dc916f572a55b0d13de7b22ad",
          "body": "…k=self (close #919) (#927)\n\n* fix: Reject a dangerous image/icon target promoted to an href via link=self (close #919)\n\nAn `image:`/`icon:` macro whose target carries a script-capable scheme\n(`javascript:`, `vbscript:`, or a non-image `data:` such as\n`data:text/html,…`) is harmless in the `<img src\n[…]\nage data URIs and trusted embedded SVGs (the Asciidoctor-parity case) live.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Reject a dangerous image/icon target promoted to an href via lin…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T14:27:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "08944ce4a76acacdb4515e1b549df4728080162e",
          "body": "…r (close #898) (#934)\n\nPath resolution was the one extensibility seam in the crate that could not\nbe swapped: `PathResolver` was a concrete struct exposed as a `pub` by-value\nfield on `Parser`, so an Antora/Zola-style host needing custom path or URL\nrewriting (virtual filesystems, content roots, UR\n[…]\n` field is now `pub(crate) Rc<dyn PathResolver>`,\nconfigured through a new `with_path_resolver(...)` builder rather than direct\nfield mutation.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor!: Make PathResolver a trait with a with_path_resolver builde…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T14:21:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d01724d237725af16b2892d5572cc95e102b7443",
          "body": "…I (close #894) (#930)\n\n* feat!: replace IsBlock::nested_blocks with a complete child_blocks API (close #894)\n\nThe discoverable block accessor `IsBlock::nested_blocks()` silently omitted\nMarkdown-blockquote children (reachable only via `QuoteBlock::blocks()`) and\nAsciiDoc table-cell content, so tool\n[…]\nck`, and\n  the `nth` override) generated by the `opaque_slice_iter!` macro.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat!: Replace IsBlock::nested_blocks with a complete child_blocks AP…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T14:18:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6dbdb248bb87626baa8087ac7c6ef5cbc0f52de9",
          "body": "…#903) (#931)\n\n* fix: Enforce SourceMap append ordering with a debug assertion (close #903)\n\n`SourceMap::resolve` binary-searches `segments` by `output_line`, which\nsilently returns garbage on an unsorted slice. `append` documented that\nentries \"should\" arrive in increasing order but did not enforce\n[…]\nptile-apps[bot]@users.noreply.github.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>\nCo-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: Enforce SourceMap append ordering with a debug assertion (close …",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T14:14:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5cb17dc58929cd6e654764f8b50a06e222229607",
          "body": "…se #899) (#926)\n\n`Catalog::ids()` and `Catalog::entries()` iterated a randomly-seeded\n`HashMap`, so their order varied between process runs. A multi-document\npipeline that derives output from catalog iteration order (e.g. building a\nglobal cross-reference index, or resolving a collision as \"first s\n[…]\nookups. `DebugHashMapFrom` is generalized to render either map type and\nstill sorts its own output, so the `Debug` representation is unchanged.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Make catalog ID iteration deterministic across process runs (clo…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T14:02:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7f1df812544eadf0f48551d0b98abfba3a438e77",
          "body": "…e #906) (#925)\n\nThe doc comment read only \"Alternative to\" with a TODO placeholder. Describe\nthat `LookaheadReplacer` is an alternative to `regex::Replacer` that can inspect\nthe text following a match and reject it via `SkipAheadAndRetry`, modeling the\nlook-ahead pattern that `regex::Replacer` cannot express.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: Complete the truncated doc comment on `LookaheadReplacer` (clos…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T13:34:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8eef1e68450f576f513f568f1a1a33d8daf724ff",
          "body": "…K branch (close #908) (#928)\n\nThe invalid-macro-syntax `else` branch in `InlineLinkReplacer` carried a\nFIXME noting that a `link:` prefix should never reach it: the shared\nNON-ANGLE branch of `INLINE_LINK` let `link:` prefix a bare (bracket-less)\nURL, which then matched and was rejected as invalid \n[…]\nsyntax path.\n\n`NormalizedCaps` gains a third branch mapping and `bare` becomes optional\n(the LINK-MACRO branch always has a trailing attrlist).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: Give the `link:` prefix its own bracket-required INLINE_LIN…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T13:32:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "024721f9252180c4962152effea6365cc966c97d",
          "body": "Settles several pre-1.0 public-API commitments flagged in the adversarial\nreview, each of which would become a breaking change to fix after the freeze:\n\n- Rename the misspelled trait method\n  `InlineSubstitutionRenderer::render_quoted_substitition` to\n  `render_quoted_substitution`.\n- Remove the pro\n[…]\n type and\n`LinkRenderParams::type_` field are removed; and `LinkRenderParams::window`\nchanges from `Option<&'static str>` to `Option<&'a str>`.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor!: Polish public rendering API ahead of 1.0 (close #897) (#929)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T13:30:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "91abb32cc09f6a331ac1c2898655248cb54037be",
          "body": "…ion (close #889) (#920)\n\nAdd a prominent \"Security: rendering untrusted input\" section to the\nREADME (which is also the crate-level doc via `include_str!`), stating\nthat the HTML renderer is not a sanitizer, that attribute-reference\nsubstitution and passthroughs emit raw HTML by design, and that\nco\n[…]\noc must run the output\nthrough an HTML sanitizer such as `ammonia`. Clarify that safe mode\ngoverns file/environment reach, not output escaping.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: Document that untrusted AsciiDoc output requires HTML sanitizat…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T05:14:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "870609273fe4653c8dd8ecea622099c3543654ff",
          "body": "…05) (#924)\n\n* perf: Reduce allocations in the inline substitution pipeline (close #905)\n\nResidual allocation-reduction items from the adversarial review; each is\nsmall and mechanical, and the many-small-blocks-of-plain-prose throughput\ncase benefits from all of them.\n\n- `apply_special_characters` n\n[…]\nng both the\n  no-op-filter borrow branch and the changed-text owned branch.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Reduce allocations in the inline substitution pipeline (close #9…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T05:14:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e053106f32bb6358554dfd2f3fc584574ff3e393",
          "body": "…ounds slice (close #902) (#923)\n\n* fix: Fall back to an empty span instead of the whole span on out-of-bounds slice (close #902)\n\n`Span::slice` / `slice_from` / `slice_to` guarded their bounds only with a\n`debug_assert!`. In a release build, when `.get(range)` returned `None`, the\n`map_or(*self, …)\n[…]\nes;\nthe release fallback behavior is already covered by the `empty()` test.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Fall back to an empty span instead of the whole span on out-of-b…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T05:13:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6ad42b74d3ae456eeccab4f1f7a6dc8504208804",
          "body": "…ciiDoc table cells (close #904) (#922)\n\nFor every AsciiDoc-style (`a`) table cell, `process_content` rebuilt the\nattribute-lock set from scratch, allocating an owned `String` for each of the\n~74 built-in attributes it locked and deep-cloning the whole `HashSet<String>`\nper cell. This was the domina\n[…]\ncall out of the modifiable-attributes loop so the\nper-parser attribute map is made-mut once per cell rather than re-checked on\nevery iteration.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf: Avoid per-cell String allocations when locking attributes in As…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T05:07:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "24ec6d181229f6d09f8dccdcf646fbd5ef918cad",
          "body": "…or (close #907) (#921)\n\nThe `// TODO:` in `section_to_node` described how the section title heading is\nadded in the `Block::Section` match arm (using `section.level()` for the heading\nlevel and `section.section_title()` for the text). That behavior is already fully\nimplemented there, so the note tr\n[…]\nfold its one useful detail (the title heading, like the id,\nlands on the heading rather than the wrapper `<div>`) into the surrounding\ncomment.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: Remove stale TODO restating implemented section-heading behavi…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T05:07:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "80825d50579108831d9bc1f96f5a6e9e43d86cdd",
          "body": "…idelity (#917)\n\n* feat: Map preprocessed spans back to origin file, line, column, and fidelity (close #891)\n\nSpans carry coordinates relative to the single preprocessed buffer, and the\nonly way back to an origin was `SourceMap::original_file_and_line`, which is\nline-only and cannot say whether a li\n[…]\nhe included file's identity is\nnot carried forward into the parent's lines.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: Map preprocessed spans back to origin file, line, column, and f…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T04:47:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e64f4ade1fff3da5fba49aebf0aba8c2fb15d6dd",
          "body": "…k macro (close #888) (#911)\n\n* fix: Escape href/target/icon attributes and reject script URIs in link macro (close #888)\n\nSeveral `href`/`target` and icon attribute values were emitted into the\nrendered HTML without escaping the `\"` delimiter, allowing an author to\nbreak out of the attribute and in\n[…]\nnd `render_icon_or_image` (which drops the\nlive link) share one definition.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Escape href/target/icon attributes and reject script URIs in lin…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T01:59:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0c93961c8288c853f6300d9487cb0139a3afe9b2",
          "body": "A UTF-8 byte-order mark (`EF BB BF` = U+FEFF) at the start of the input\nwas not stripped. `preprocess` short-circuits and returns the source\nunchanged when there are no directives, so the U+FEFF became the first\ncharacter of the first line. `Header::parse` requires the line to start\nwith `= `, so a \n[…]\n This matches Asciidoctor, which strips a UTF-8 BOM even\nfor UTF-8 input, and is independent of UTF-16 transcoding, which remains\nout of scope.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Strip a leading UTF-8 BOM before parsing (close #900) (#918)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T01:45:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "436d8144f64c066572d62d4581da228bf52601ec",
          "body": "…nput (close #885) (#910)\n\n* fix: Cap block nesting depth to prevent stack overflow on untrusted input (close #885)\n\nBlock parsing descends recursively through `parse_blocks_until` (delimited\nblock bodies, section bodies, table cells, quote/blockquote content) and\nthrough `ListBlock::parse_inside_li\n[…]\ntores parity with\nthe pre-#885 baseline (measured within run-to-run noise).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Cap block nesting depth to prevent stack overflow on untrusted i…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T01:30:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9c91f6f9c6f3916cb55ae67e3fbfeccfb3bfa644",
          "body": "…r (close #893) (#909)\n\n* fix: Reset document attribute values between parses on a reused Parser (close #893)\n\n`Parser::parse_deferred` reset the catalog, callouts, substitution\nwarnings, section numbering, pending block title, and counters between\nparses but not `attribute_values`, so document-head\n[…]\nic's prose dash convention in the doc comment added by the\nprevious commit.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Reset document attribute values between parses on a reused Parse…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T01:08:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c8aa0e203b0f9a0374a288eab5fcd69524e2134d",
          "body": "…ad (close #887) (#912)\n\n* fix: Honor char boundary when skipping constrained-monospace look-ahead (close #887)\n\nThe constrained-monospace quote regex's leading boundary group\n`[^\\w&;:\"'`}]` matches any non-word Unicode scalar, including multi-byte\ncharacters. When a failed look-ahead skipped the le\n[…]\nage gap left by\nthe multi-byte fix. The escaped text is preserved verbatim.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Honor char boundary when skipping constrained-monospace look-ahe…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T00:40:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "50f578e127fe1a0c76989d01cbf6a21aa8b9a28c",
          "body": "Apply the documented comment/doc style conventions to hand-written\ncomments and documentation text (excluding the vendored `ref/` tree and\nthe tests that quote it):\n\n- Convert prose em dashes to spaced en dashes (366 lines). The one\n  literal em-dash character reference in `virtual_dom.rs` is preser\n[…]\nn test it marks.\n- File tracking issues for an incomplete doc comment and two unlinked\n  TODO/FIXME comments, and link them (#906, #907, #908).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "doc: Normalize comment and doc prose style across the codebase (#915)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T00:37:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a43b990ea8278c9b81394ffd2bff232a57b17a60",
          "body": "…#886) (#914)\n\n* fix: Avoid O(n²) parse time on many repeated block delimiters (close #886)\n\n`QuoteBlock::parse` runs before `CompoundDelimitedBlock` in block dispatch,\nso it is tried for every delimiter line. Its quoted-paragraph path called\n`read_paragraph` (a scan to the next blank line) before t\n[…]\nlines between\nthem) — the shape that previously triggered O(n²) parse time.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Avoid O(n²) parse time on many repeated block delimiters (close …",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T00:35:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b5252cb2a4b00dd2dd93049da95c2c90d2178eb9",
          "body": "…ction (close #890) (#913)\n\nThe `Safe` and `Server` docstrings described protections the parser does\nnot actually enforce:\n\n- `Safe` claimed it prevents access to files outside the source file's\n  parent directory. This crate performs no filesystem I/O and does not\n  port Ruby Asciidoctor's `PathRes\n[…]\nent handler's responsibility —\nand that only `Secure`, not `Server`, disables include/asset embedding.\n\nDocumentation only; no behavior change.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: Correct SafeMode Safe/Server docstrings to match enforced prote…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-24T00:28:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "006b8752176d0637c7f3c2535ecbb02f5ba47798",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.25.0 (#879)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T15:21:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cfae1bd47ba42ecab7e0585b59f9f80fa7a40c81",
          "body": null,
          "is_bot": false,
          "headline": "chore: Update README to reflect fully feature-complete status (#884)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T15:15:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b2106856ea6c1c62dcd52c1021720ca2d7b5d294",
          "body": "…(close #871) (#883)\n\n* test: Verify link attrlist enclosure rule for invalid attribute names (close #871)\n\nPromote the \"enclosure only required when the text preceding the equals\nsign matches a valid attribute name\" sentence in the link/URL macro\nattribute-parsing spec from a non-normative note to \n[…]\nor future spec-coverage work and silence the\nunused-macro/-import warnings.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Verify link attrlist enclosure rule for invalid attribute names …",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T15:04:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "48407cc93dcdb2524698690360334ec80e85f99e",
          "body": "… content (close #877) (#881)\n\n`reindent_included_lines` previously returned included content unchanged\nwhenever the `indent` attribute was absent, so `tabsize`-driven tab\nexpansion only fired when `indent` was also supplied.\n\nPer the spec, when `tabsize` is set, tabs are replaced with spaces\nregard\n[…]\nxpansion now runs\nwhenever `tabsize` is positive; indentation normalization is applied\nindependently when `indent` is present and non-negative.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Expand tabs from `tabsize` independently of `indent` on included…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:53:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1c10c0badc6182a1de62af87f02a150e2f994d42",
          "body": "…ing blank lines (close #876) (#882)\n\nPromote the `to_do_verifies!` block in `document_test.rs` to two real\n`verifies!` tests, backed by an `InlineFileHandler` fixture reproducing\nAsciidoctor's canonical `include-with-leading-blank-line.adoc` (two blank\nlines before the level-0 title).\n\n- A whole-fi\n[…]\ne and sets `:toc:`.\n- `lines=6` selects by original line number, skipping the leading blank\n  lines and the title so only the section survives.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: Verify document-title & lines= selection for includes with lead…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:53:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "de9a4cff700cb105ba39c66753cc902e78bfc5a7",
          "body": "…lose #801) (#880)\n\n`WarningType` became part of the public API in #799, so its variant names\nand `Display` strings now need to read as a deliberate, consistent set. This\nis the one-time review the long-standing TODO above `InvalidMacroName` asked\nfor.\n\nVariant renames (breaking for anyone matching \n[…]\ner\"). Wording is otherwise unchanged. This changes user-visible\nwarning text.\n\nThe `TODO (#801)` marker is removed now that the review is done.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(warnings)!: Review WarningType variant names and messages (c…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:44:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0c6a48c7687d434f46b001a991b9aaae7ca4f778",
          "body": "…878)\n\nConvert the now-testable table structural-container row to verifies! and\nreclassify the permanently-unverifiable / out-of-scope blocks as\nnon_normative! with justifications:\n\n- delimited.rs: the four table delimiters (`|===`, `,===`, `:===`, `!===`)\n  now assert the `table` context and conten\n[…]\ne two genuinely-deferred blocks now cite tracking issues #876 (include\ndoctitle recognition / lines= selection) and #877 (block-level tabsize).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: Resolve remaining to_do_verifies! blocks from the #628 sweep (#…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:39:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2f37e9dd217d6c7595c77300828d290df3b15aaa",
          "body": "…) (#874)\n\n* test: Cover description-list delimiter and anchor rules (close #864)\n\nThe opening `non_normative!` block in `lists/description.rs` reproduced\nseveral normative parsing rules for description lists but none were\nexercised by a test. Split the block so the normative prose is now backed\nby \n[…]\ntrast to\na leading `[[id]]` anchor which becomes part of the rendered term.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": " chore: Cover description-list delimiter and anchor rules (close #864…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:37:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3e721feddf89a868c943c97bf3abb78d0b32387a",
          "body": "…horthand ID/role order, AsciiDoc-cell directive) (#873)\n\n* test: Cover `title`-attribute fallback for the document title\n\nSplit the `[#title-attr]` `non_normative!` block so the normative\nfallback rule is verified: with no level 0 section title and no\n`doctitle` attribute, a `title` attribute entry\n[…]\name\ndirective on the following line acts as a normal multiline conditional.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: Close mislabeled-normative coverage gaps (doctitle fallback, s…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:27:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "18685312ef868d1f9906882096a40a25a8224b63",
          "body": "…se #865) (#875)\n\nSeveral inline-macro spec pages wrapped a normative parsing rule in\n`non_normative!` without covering tests. Add `verifies!` coverage for\neach rule the parser already implements correctly, and a justified\n`to_do_verifies!` marker for the one it does not:\n\n- Inline image alt-text: a\n[…]\next before `=` is a valid attribute name. The parser does not yet\n  honor this; the marker documents current behavior and is tracked by\n  #871.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: Cover inline-macro spec rules hidden behind non_normative! (clo…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:26:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9aad9fafcabf48bfd30a115b4693f86279bde551",
          "body": "…combinators (close #866) (#868)\n\n* test: Cover mixed ifdef/ifndef combinator behavior (close #866)\n\nThe `non_normative!` block in `ifdef_ifndef.rs` stated the normative rule\nthat the `,` (or) and `+` (and) combinators cannot be combined in a single\nconditional-directive expression, but no test asse\n[…]\naffected. Extend `combinators_cannot_be_mixed` to cover the `+`-first case.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Match Asciidoctor's first-delimiter rule for mixed ifdef/ifndef …",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:14:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5051db0ceb815d7961afb2c5fc2d53131d6ee2df",
          "body": "Port Asciidoctor's `doc.register :links, target` so the parser records\nevery link target it encounters, exposed as `Catalog::links()`. Like the\nimage registry, population is gated on the `catalog_assets` option and\nrecorded in substitution-pass order.\n\nAll four Asciidoctor registration sites are covered: bare-URL autolink,\n`link:` macro, `mailto:`/link macro, and email autolink (the last of\nwhich the original TO DO markers had missed).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: Populate the document catalog's link registry (close #335) (#872)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:10:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e06f0caf0984685dcb64fa452c10e6ca152a60d2",
          "body": "Audit of commented-out code turned up two genuinely dead blocks in the\ncrate's own source (excluding quoted Asciidoctor / AsciiDoc reference\nmaterial):\n\n- `passthroughs.rs`: an abandoned trailing-backslash truncation approach,\n  superseded by the retry logic that follows it.\n- `sdd/src/main.rs`: a developer debugging shortcut that scoped file\n  processing to a single file.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: Remove commented-out dead code (close #705) (#870)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T14:09:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dbacb2413f412cdbee15fd2ebd8ff150b1c77b34",
          "body": null,
          "is_bot": false,
          "headline": "chore(asciidoc-parser): release v0.24.0 (#863)",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T04:33:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99cf75ffb9858f73cb164da754ce25058e314f13",
          "body": "…tle (#862)\n\nAdd a regression test asserting that a block attribute line above the\ndocument title whose value carries a `{counter:…}` reference does not fire\nthe counter at header time when the run is ultimately rejected (here by an\nembedded `[[anchor]]`).\n\n`document_title_follows_block_metadata` sc\n[…]\nparser and the counter advances exactly once. This\nlocks in that behavior, salvaging the one piece of unique coverage from the\nsuperseded #833.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: Cover counter deferral for a rejected metadata run above the ti…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T04:27:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0944b66c0ba58ae3c2a2dc942f070698241756d1",
          "body": "…ub (#861)\n\nIssue #308 asked whether a block title can span multiple lines via a\ntrailing `+`. The answer is no: a title is a single line, and a trailing\n` +` is retained literally rather than joined to the following line\n(confirmed against the parser). Replace the stale `TO DO` comment linking\nto #\n[…]\n `to_do_verifies!` stub convention.\n\nThe `|Titles |{y}` spec-coverage marker stays; that gap is tracked by the\n`to_do_verifies!` sweep in #628.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: Remove resolved #308 reference from post_replacements titles st…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T04:07:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "adf9ff733355bea5b2dba6b52c30deb736ecbc0d",
          "body": "…9) (#852)\n\n* fix: Fuse legacy `+`-continued multi-line attribute values (close #729)\n\nAn attribute entry value can be continued across lines with a trailing\n` +` (legacy) as well as ` \\` (modern). Previously only the backslash\ncontinuation was fused; a legacy `+`-continued value was not joined — th\n[…]\nn the document body).\n\nAdds span-, fold-, and parse-level regression tests.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Fuse legacy `+`-continued multi-line attribute values (close #72…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T04:06:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3f2e0d78c748fff27314a181285a2863f43d4b05",
          "body": "…732) (#850)\n\n* fix: Formal `role=` replaces roles set via shorthand `.role` (close #732)\n\nWhen merging multiple block attribute lines, roles now follow\nAsciidoctor's running model: a formal `role=` entry replaces every role\naccumulated so far, while shorthand `.role` entries append. Previously\nall \n[…]\nat\n  the formal value replaces the running roles and the shorthand appends.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: Formal `role=` replaces roles set via shorthand `.role` (close #…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T03:59:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cab8554693ddb8d05d68eb5dd37bdf05384d37ff",
          "body": "…lose #745) (#848)\n\n* feat: Drop YAML/TOML front matter when `skip-front-matter` is set (close #745)\n\nA `---`-fenced block at the very top of the document is now removed – and\nits content captured in the `front-matter` document attribute – when the\n`skip-front-matter` attribute is set, mirroring Asc\n[…]\n, `+++` TOML is not, and the content is\nstored verbatim rather than parsed.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: Drop YAML-style front matter when `skip-front-matter` is set (c…",
          "author_name": "Eric Scouten",
          "author_login": "scouten",
          "committed_at": "2026-07-23T03:54:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 55,
      "commits_last_year": 546,
      "latest_release_at": "2026-08-01T16:14:24Z",
      "latest_release_tag": "v0.29.4",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 37,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 0.7
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 37,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "sdd",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "concurrent",
            "garbage",
            "memory",
            "epoch",
            "lock-free",
            "data-structures",
            "concurrency",
            "memory-management"
          ],
          "ecosystem": "crates",
          "matches_repo": false,
          "registry_url": "https://crates.io/crates/sdd",
          "is_deprecated": false,
          "latest_version": "4.8.8",
          "repository_url": "https://codeberg.org/wvwwvwwv/scalable-delayed-dealloc",
          "versions_count": 72,
          "total_downloads": 77608068,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 5899173,
          "first_published_at": "2024-04-14T18:03:40.616625Z",
          "latest_published_at": "2026-07-02T14:12:15.625601Z",
          "latest_version_yanked": false,
          "days_since_latest_publish": 30
        },
        {
          "name": "asciidoc-parser",
          "exists": true,
          "license": "MIT OR Apache-2.0",
          "keywords": [
            "parser",
            "asciidoc",
            "parser-implementations"
          ],
          "ecosystem": "crates",
          "matches_repo": true,
          "registry_url": "https://crates.io/crates/asciidoc-parser",
          "is_deprecated": false,
          "latest_version": "0.29.4",
          "repository_url": "https://github.com/asciidoc-rs/asciidoc-parser",
          "versions_count": 55,
          "total_downloads": 13542,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 2012,
          "first_published_at": "2024-10-26T22:27:57.063155Z",
          "latest_published_at": "2026-08-01T16:14:20.394752Z",
          "latest_version_yanked": false,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 4,
      "stars": 34,
      "watchers": 2,
      "fork_history": {
        "days": [
          {
            "date": "2026-01-23",
            "count": 1
          },
          {
            "date": "2026-02-17",
            "count": 1
          },
          {
            "date": "2026-04-01",
            "count": 1
          },
          {
            "date": "2026-07-18",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 4,
        "total_forks": 4
      },
      "star_history": null,
      "open_issues_and_prs": 5
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": true,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "Cargo.toml",
        "parser/Cargo.toml",
        "sdd/Cargo.toml"
      ],
      "largest_source_bytes": 434972,
      "source_files_sampled": 419,
      "oversized_source_files": 45,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "Cargo.toml",
        "parser/Cargo.toml",
        "sdd/Cargo.toml"
      ],
      "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": 10,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "crates"
      ],
      "dependencies": [
        {
          "name": "bytecount",
          "manifest": "parser/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.6.7"
        },
        {
          "name": "memchr",
          "manifest": "parser/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "2.6.4"
        },
        {
          "name": "percent-encoding",
          "manifest": "parser/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "2.3.2"
        },
        {
          "name": "regex",
          "manifest": "parser/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.11.1"
        },
        {
          "name": "self_cell",
          "manifest": "parser/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.2.0"
        },
        {
          "name": "thiserror",
          "manifest": "parser/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "2.0.1"
        },
        {
          "name": "walkdir",
          "manifest": "sdd/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "2.5"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "bytecount",
            "direct": true,
            "version": null,
            "ecosystem": "crates"
          },
          {
            "name": "memchr",
            "direct": true,
            "version": null,
            "ecosystem": "crates"
          },
          {
            "name": "percent-encoding",
            "direct": true,
            "version": null,
            "ecosystem": "crates"
          },
          {
            "name": "regex",
            "direct": true,
            "version": null,
            "ecosystem": "crates"
          },
          {
            "name": "self_cell",
            "direct": true,
            "version": null,
            "ecosystem": "crates"
          },
          {
            "name": "thiserror",
            "direct": true,
            "version": null,
            "ecosystem": "crates"
          },
          {
            "name": "walkdir",
            "direct": true,
            "version": null,
            "ecosystem": "crates"
          },
          {
            "name": "codspeed-criterion-compat",
            "direct": false,
            "version": null,
            "ecosystem": "crates"
          },
          {
            "name": "criterion",
            "direct": false,
            "version": null,
            "ecosystem": "crates"
          },
          {
            "name": "pretty_assertions_sorted",
            "direct": false,
            "version": null,
            "ecosystem": "crates"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 10,
        "direct_count": 7,
        "indirect_count": 3
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 2,
        "merged_prs": 772,
        "open_issues": 3,
        "closed_ratio": 0.987,
        "closed_issues": 223,
        "closed_unmerged_prs": 40
      },
      "bus_factor": 2,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "scouten",
          "commits": 759,
          "avatar_url": "https://avatars.githubusercontent.com/u/158391?v=4"
        },
        {
          "type": "User",
          "login": "mojavelinux",
          "commits": 723,
          "avatar_url": "https://avatars.githubusercontent.com/u/79351?v=4"
        },
        {
          "type": "User",
          "login": "graphitefriction",
          "commits": 37,
          "avatar_url": "https://avatars.githubusercontent.com/u/1124042?v=4"
        },
        {
          "type": "User",
          "login": "ggrossetie",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/333276?v=4"
        },
        {
          "type": "User",
          "login": "larryv",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/281175?v=4"
        },
        {
          "type": "User",
          "login": "mmattel",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/3321281?v=4"
        },
        {
          "type": "User",
          "login": "ahus1",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/3957921?v=4"
        },
        {
          "type": "User",
          "login": "btat",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/1832069?v=4"
        },
        {
          "type": "User",
          "login": "Vampire",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/325196?v=4"
        },
        {
          "type": "User",
          "login": "danyill",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/674783?v=4"
        }
      ],
      "contributors_sampled": 22,
      "top_contributor_share": 0.492
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "pr_title.yml",
        "release.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 3,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "30 out of 30 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 1/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 14 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": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 30 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": 10,
            "reason": "all dependencies are pinned",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "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": "85320d8042ad10832b6e6cdc5cc7f7ef740c558f",
        "ran_at": "2026-08-01T18:21:44Z",
        "aggregate_score": 6.1,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-08-01T17:56:39Z",
      "oldest_open_prs": [
        {
          "number": 1039,
          "created_at": "2026-08-01T17:54:25Z",
          "last_comment_at": "2026-08-01T17:57:42Z",
          "last_comment_author": "codspeed-hq"
        },
        {
          "number": 1040,
          "created_at": "2026-08-01T18:13:36Z",
          "last_comment_at": "2026-08-01T18:16:29Z",
          "last_comment_author": "codspeed-hq"
        }
      ],
      "last_merged_pr_at": "2026-08-01T17:53:45Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 943,
          "created_at": "2026-07-24T22:37:22Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 944,
          "created_at": "2026-07-24T22:37:43Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1036,
          "created_at": "2026-08-01T17:29:43Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/asciidoc-rs/asciidoc-parser",
    "host": "github.com",
    "name": "asciidoc-parser",
    "owner": "asciidoc-rs"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": "The weighted overall 66 is calibrated to 77 on the published index scale (record calibration 2026-08-02).",
      "notes": [
        {
          "code": "overall_calibration",
          "params": {
            "raw": 66,
            "calibrated": 77,
            "calibration": "2026-08-02"
          }
        }
      ],
      "value": 77,
      "inputs": {
        "security": 61,
        "vitality": 94,
        "community": 43,
        "governance": 66,
        "calibration": "2026-08-02",
        "engineering": 61,
        "ai_readiness": 64,
        "weighted_overall_raw": 66
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "exceptional",
        "name": "Vitality",
        "value": 94,
        "weight": 0.21,
        "metrics": [
          {
            "key": "development_activity",
            "band": "excellent",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "commits_last_year": 546,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 37
            },
            "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": "37/52 weeks with commits",
                "points": 25.6,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 37
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "546 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 546
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "exceptional",
            "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": 100,
            "inputs": {
              "releases_count": 55,
              "latest_release_tag": "v0.29.4",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 0.7
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "55 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 55
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~0.7 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0.7
                    }
                  }
                ],
                "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": "exceptional",
            "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": 3,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 3 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "weak",
        "name": "Community & Adoption",
        "value": 43,
        "weight": 0.17,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 29,
            "inputs": {
              "forks": 4,
              "stars": 34,
              "watchers": 2,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "34 stars",
                "points": 24.6,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 34
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "4 forks",
                "points": 4,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "2 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "readme_badges": null,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "readme_badge_services": [],
              "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 (Apache-2.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "Apache-2.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": "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": 55,
            "inputs": {
              "packages": [
                "asciidoc-parser"
              ],
              "dependents": null,
              "ecosystems": "crates",
              "total_downloads": 13542,
              "monthly_downloads": 2012
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "2,012 downloads/month across crates",
                "points": 44.1,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 2012,
                      "ecosystems": "crates"
                    }
                  }
                ],
                "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": "good",
        "name": "Sustainability & Governance",
        "value": 66,
        "weight": 0.23,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "moderate",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "bus_factor": 2,
              "contributors_sampled": 22,
              "top_contributor_share": 0.492
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "2 contributor(s) cover half of all commits",
                "points": 25.2,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 49% of commits",
                "points": 11.4,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 49
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "22 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 22
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 14 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Newcomer PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "newcomer_pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 80,
            "inputs": {
              "merged_prs": 772,
              "open_issues": 3,
              "closed_issues": 223,
              "prs_merged_7d": null,
              "prs_decided_7d": null,
              "prs_merged_30d": null,
              "prs_decided_30d": null,
              "issue_closed_ratio": 0.987,
              "closed_unmerged_prs": 40,
              "first_time_authors_30d": null,
              "first_time_prs_merged_30d": null,
              "first_time_prs_decided_30d": null
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "99% of issues closed",
                "points": 41.5,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 99
                    }
                  }
                ],
                "max_points": 42
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "772/812 decided PRs merged",
                "points": 28.5,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 772,
                      "decided": 812
                    }
                  }
                ],
                "max_points": 30
              },
              {
                "key": "newcomer_pr_acceptance",
                "name": "Newcomer PR acceptance",
                "detail": "no first-time contributor's PR decided in 30d",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_newcomer_prs",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 13
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 1/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 34,
            "inputs": {
              "followers": 0,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "asciidoc-rs",
              "public_repos": 2,
              "account_age_days": 175
            },
            "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": "0 followers of asciidoc-rs",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 0,
                      "login": "asciidoc-rs"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "2 public repos, account ~0 yr old",
                "points": 4.4,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 2
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "exceptional",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "asciidoc-parser"
              ],
              "ecosystems": "crates",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on crates",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "crates"
                    }
                  }
                ],
                "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": "55 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 55
                    }
                  }
                ],
                "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": 61,
        "weight": 0.19,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "3 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "30 out of 30 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": [
                "asciidoc",
                "markup",
                "parser"
              ],
              "has_wiki": false,
              "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": "3 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 61,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 61,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 6.1
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "30 out of 30 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 1/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 14 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": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 30 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": "all dependencies are pinned",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "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": "exceptional",
            "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"
              ],
              "commit_weight_rule": {
                "min_commits": 50,
                "min_commit_share": 0.1
              },
              "review_only_matches": 0,
              "below_threshold_exposures": [],
              "assessed_self_published_locations": 21
            },
            "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": 64,
        "weight": 0.04,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "weak",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "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": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "excellent",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 81,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": true,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.86,
              "toolchain_manifests": [
                "Cargo.toml",
                "parser/Cargo.toml",
                "sdd/Cargo.toml"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Cargo.toml, parser/Cargo.toml, sdd/Cargo.toml (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "Cargo.toml, parser/Cargo.toml, sdd/Cargo.toml"
                    }
                  }
                ],
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Rust (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Rust"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "devcontainer",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "devcontainer"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "86 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 86,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "dependency automation configured, none observed in the sampled commits",
                "points": 5,
                "status": "partial",
                "details": [
                  {
                    "code": "dependency_bot_config_only",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "all dependencies are pinned",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "exceptional",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 94,
            "inputs": {
              "primary_language": "Rust",
              "largest_source_bytes": 434972,
              "source_files_sampled": 419,
              "oversized_source_files": 45
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Rust (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Rust"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "45/419 source files over 60KB",
                "points": 49.1,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 419,
                      "oversized": 45
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "weak",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
      }
    ],
    "classification": {
      "top": [
        "library"
      ],
      "labels": [
        "library"
      ],
      "scores": {
        "library": 6
      },
      "primary": "library",
      "evidence": [
        {
          "tier": "distribution",
          "label": "library",
          "source": "registry:crates",
          "weight": 6
        }
      ],
      "artifacts": [],
      "confidence": "medium",
      "host_extension": false,
      "runs_as_process": false,
      "consumed_by_code": true
    },
    "metrics_version": "2.5.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "crates package 'sdd' points at a different repository (https://codeberg.org/wvwwvwwv/scalable-delayed-dealloc); excluded from ecosystem scoring",
    "deps.dev does not index crates:asciidoc-parser@0.29.4; advisories assessed against the repository dependency graph instead",
    "No resolved dependencies carried a version and a supported ecosystem"
  ],
  "report_type": "repository",
  "generated_at": "2026-08-01T18:22:10.907697Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/a/asciidoc-rs/asciidoc-parser.svg",
  "full_name": "asciidoc-rs/asciidoc-parser",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

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

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

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