chore: CHANGELOG.adoc asciidoctor render hygiene sweep

Description

CHANGELOG.adoc renders with multiple structural malformations under asciidoctor. None affect the eventual published behaviour (the entries are still readable as raw AsciiDoc), but the rendered HTML carries broken inline-formatting that future contributors will perpetuate by copy-pasting the existing patterns. The fixes are mechanical but touch ~20 entries.

Verified 2026-05-18 against asciidoctor CHANGELOG.adoc -o /tmp/changelog.html at HEAD of feature/canopy-api-retry-middleware.

Specific malformations

  1. #NNN refs collide with AsciiDoc #...# mark/highlight syntax. 19 <mark> spans in the rendered HTML span across multiple entries. Example: line 24's #473 + #477 ... #[cfg(test)] (and similar mixes of issue refs + Rust attribute syntax) produce mangled <mark>...</mark> wraps around <code>[default]</code>, sqlx <code>... etc.
  2. Backticks do not protect _, *, # from emphasis parsing. CANOPY_SNAP_RULES_URL inside backticks renders as <code>CANOPY_SNAP<em>RULES</em>URL</code>. Same pattern for _sqlx_migrations, test_*, and globs like services/**/tests/.
  3. Indented Markdown sub-bullets become <div class="literalblock">. Lines ~747-759 (audit-chain bug entry) render as seven separate literal blocks with raw **Bug 1...** text instead of nested AsciiDoc bullets.
  4. Nested <strong> from **Phase E** inside bullet titles. Cosmetic — render is ugly but legible.
  5. ... inside code spans gets smart-replaced to &#8230;&#8203;. Cosmetic, applies broadly.

Cleanup recipe

  • Escape every #NNN not inside a real markdown link as \#NNN, OR convert to full GitLab URLs (https://gitlab.com/gadhs/application/eligibility/canopy/-/issues/NNN[#NNN]).
  • Replace fragile inline code with AsciiDoc passthrough monospace: +_sqlx_migrations+, +services/**/tests/+, +test_*+, +#[ignore]+, etc.
  • Convert indented Markdown sub-bullets to AsciiDoc nested bullets (**).
  • For bullet titles, prefer single-* AsciiDoc bold over Markdown **...** to avoid nested-emphasis.
  • Re-render after each pass and grep for <mark>, <code><em>, <code><strong>.

Blame decoupling policy

The cleanup MR should be a single sweep commit with the message:

chore: structural AsciiDoc fixes in CHANGELOG.adoc — no semantic change to any entry

body: enumerate the four fix patterns + cite this issue.

Rationale: each CHANGELOG entry already self-cites its producing commit / MR (Closes #N, (!M), (#NNN) markers in the entry text), so the entry-to-commit link survives in the entry text even when git blame points at the cleanup commit. git log -p CHANGELOG.adoc still shows when each entry first landed, regardless of later reformatting. Only naive git blame is degraded — git log --follow -p recovers the history. Per-entry commit chain (20 commits) was considered but rejected as churn-vs-recovery-value not worth it for a self-citing append-only file.

Acceptance Criteria

  • asciidoctor CHANGELOG.adoc -o /tmp/check.html produces zero <mark> spans.
  • Zero <code> spans contain <em> or <strong> children.
  • Zero <div class="literalblock"> from indented Markdown bullets.
  • Each entry's title bold uses *...* (constrained) rather than **...** (Markdown), unless the bold needs to span a non-word boundary.
  • No content change to the entries — only structural escaping / passthrough conversion.
  • Single sweep commit per the blame-decoupling policy above.

Context & References

  • Discovered during: #462 (closed) (retry middleware) review — the retry entry itself is clean, but the review surfaced 19+ pre-existing malformations.
  • Affected file: CHANGELOG.adoc
  • Recipe source: external rendered-HTML audit 2026-05-18.

Labels

priority::low, service::ci, program::infrastructure, type::documentation, workflow::ready