Apr 22, 8-9 PM (15)
Apr 22, 9-10 PM (23)
Apr 22, 10-11 PM (31)
Apr 22, 11-12 AM (17)
Apr 23, 12-1 AM (7)
Apr 23, 1-2 AM (4)
Apr 23, 2-3 AM (4)
Apr 23, 3-4 AM (6)
Apr 23, 4-5 AM (3)
Apr 23, 5-6 AM (8)
Apr 23, 6-7 AM (17)
Apr 23, 7-8 AM (26)
Apr 23, 8-9 AM (33)
Apr 23, 9-10 AM (33)
Apr 23, 10-11 AM (29)
Apr 23, 11-12 PM (30)
Apr 23, 12-1 PM (51)
Apr 23, 1-2 PM (69)
Apr 23, 2-3 PM (74)
Apr 23, 3-4 PM (26)
Apr 23, 4-5 PM (22)
Apr 23, 5-6 PM (7)
Apr 23, 6-7 PM (7)
Apr 23, 7-8 PM (11)
Apr 23, 8-9 PM (14)
Apr 23, 9-10 PM (6)
Apr 23, 10-11 PM (28)
Apr 23, 11-12 AM (18)
Apr 24, 12-1 AM (7)
Apr 24, 1-2 AM (4)
Apr 24, 2-3 AM (7)
Apr 24, 3-4 AM (5)
Apr 24, 4-5 AM (8)
Apr 24, 5-6 AM (13)
Apr 24, 6-7 AM (12)
Apr 24, 7-8 AM (33)
Apr 24, 8-9 AM (40)
Apr 24, 9-10 AM (41)
Apr 24, 10-11 AM (72)
Apr 24, 11-12 PM (57)
Apr 24, 12-1 PM (100)
Apr 24, 1-2 PM (57)
Apr 24, 2-3 PM (35)
Apr 24, 3-4 PM (19)
Apr 24, 4-5 PM (16)
Apr 24, 5-6 PM (38)
Apr 24, 6-7 PM (27)
Apr 24, 7-8 PM (12)
Apr 24, 8-9 PM (42)
Apr 24, 9-10 PM (17)
Apr 24, 10-11 PM (30)
Apr 24, 11-12 AM (16)
Apr 25, 12-1 AM (8)
Apr 25, 1-2 AM (1)
Apr 25, 2-3 AM (10)
Apr 25, 3-4 AM (5)
Apr 25, 4-5 AM (3)
Apr 25, 5-6 AM (13)
Apr 25, 6-7 AM (1)
Apr 25, 7-8 AM (4)
Apr 25, 8-9 AM (24)
Apr 25, 9-10 AM (17)
Apr 25, 10-11 AM (4)
Apr 25, 11-12 PM (4)
Apr 25, 12-1 PM (13)
Apr 25, 1-2 PM (3)
Apr 25, 2-3 PM (10)
Apr 25, 3-4 PM (6)
Apr 25, 4-5 PM (10)
Apr 25, 5-6 PM (16)
Apr 25, 6-7 PM (13)
Apr 25, 7-8 PM (30)
Apr 25, 8-9 PM (55)
Apr 25, 9-10 PM (13)
Apr 25, 10-11 PM (21)
Apr 25, 11-12 AM (22)
Apr 26, 12-1 AM (5)
Apr 26, 1-2 AM (0)
Apr 26, 2-3 AM (2)
Apr 26, 3-4 AM (5)
Apr 26, 4-5 AM (2)
Apr 26, 5-6 AM (2)
Apr 26, 6-7 AM (3)
Apr 26, 7-8 AM (8)
Apr 26, 8-9 AM (3)
Apr 26, 9-10 AM (0)
Apr 26, 10-11 AM (2)
Apr 26, 11-12 PM (1)
Apr 26, 12-1 PM (6)
Apr 26, 1-2 PM (4)
Apr 26, 2-3 PM (14)
Apr 26, 3-4 PM (14)
Apr 26, 4-5 PM (0)
Apr 26, 5-6 PM (13)
Apr 26, 6-7 PM (13)
Apr 26, 7-8 PM (7)
Apr 26, 8-9 PM (7)
Apr 26, 9-10 PM (5)
Apr 26, 10-11 PM (27)
Apr 26, 11-12 AM (21)
Apr 27, 12-1 AM (7)
Apr 27, 1-2 AM (7)
Apr 27, 2-3 AM (9)
Apr 27, 3-4 AM (9)
Apr 27, 4-5 AM (5)
Apr 27, 5-6 AM (13)
Apr 27, 6-7 AM (7)
Apr 27, 7-8 AM (82)
Apr 27, 8-9 AM (47)
Apr 27, 9-10 AM (33)
Apr 27, 10-11 AM (62)
Apr 27, 11-12 PM (80)
Apr 27, 12-1 PM (66)
Apr 27, 1-2 PM (44)
Apr 27, 2-3 PM (52)
Apr 27, 3-4 PM (42)
Apr 27, 4-5 PM (36)
Apr 27, 5-6 PM (26)
Apr 27, 6-7 PM (13)
Apr 27, 7-8 PM (26)
Apr 27, 8-9 PM (13)
Apr 27, 9-10 PM (15)
Apr 27, 10-11 PM (42)
Apr 27, 11-12 AM (28)
Apr 28, 12-1 AM (17)
Apr 28, 1-2 AM (8)
Apr 28, 2-3 AM (4)
Apr 28, 3-4 AM (5)
Apr 28, 4-5 AM (5)
Apr 28, 5-6 AM (8)
Apr 28, 6-7 AM (8)
Apr 28, 7-8 AM (37)
Apr 28, 8-9 AM (54)
Apr 28, 9-10 AM (59)
Apr 28, 10-11 AM (53)
Apr 28, 11-12 PM (56)
Apr 28, 12-1 PM (49)
Apr 28, 1-2 PM (53)
Apr 28, 2-3 PM (68)
Apr 28, 3-4 PM (31)
Apr 28, 4-5 PM (14)
Apr 28, 5-6 PM (47)
Apr 28, 6-7 PM (9)
Apr 28, 7-8 PM (9)
Apr 28, 8-9 PM (14)
Apr 28, 9-10 PM (20)
Apr 28, 10-11 PM (34)
Apr 28, 11-12 AM (29)
Apr 29, 12-1 AM (13)
Apr 29, 1-2 AM (1)
Apr 29, 2-3 AM (1)
Apr 29, 3-4 AM (6)
Apr 29, 4-5 AM (1)
Apr 29, 5-6 AM (4)
Apr 29, 6-7 AM (12)
Apr 29, 7-8 AM (45)
Apr 29, 8-9 AM (70)
Apr 29, 9-10 AM (49)
Apr 29, 10-11 AM (25)
Apr 29, 11-12 PM (50)
Apr 29, 12-1 PM (39)
Apr 29, 1-2 PM (21)
Apr 29, 2-3 PM (66)
Apr 29, 3-4 PM (25)
Apr 29, 4-5 PM (36)
Apr 29, 5-6 PM (16)
Apr 29, 6-7 PM (10)
Apr 29, 7-8 PM (14)
Apr 29, 8-9 PM (9)
3,750 commits this week Apr 22, 2026 - Apr 29, 2026
Address carbolymer review on PR #1180
- Changelog (.changes/.../fix_haddock_links.yml): collapse the
  description block scalar to a single line, removing the hard wraps
  Herald renders verbatim (r3159565460).

- derive_name_candidates (scripts/fix-haddock-links.sh): cap at
  two-token names. The previous loop emitted a single-token URL like
  cardano.cardano.intersectmbo.org as its last candidate; if that
  subdomain ever resolves (wildcard DNS, future deploy, catch-all),
  probe_site silently accepts it and rewrites every cardano-* link to
  the wrong site. Add an early break after the suffix strip so the
  heuristic never emits a URL whose subdomain is a single bare token
  (r3159784338).

- curl retries (scripts/fix-haddock-links.sh): every probe was a
  single-shot attempt (5s connect, 10s max) with no retry. Worst case:
  Phase 3 validation downgrades a perfectly valid rewritten URL into
  an unclickable <span>, silently shipping a regression. Other failure
  modes: probe_site falling through to a wrong candidate, or the CHaP
  index fetch killing the whole build on a CDN hiccup. Add
  --retry 3 --retry-delay 2 --retry-all-errors to all five curl sites
  (r3159784102).

- Workflow assignee 422 (.github/workflows/github-page.yml): the
  GitHub API rejects assignees that aren't repo collaborators with a
  422. If an external contributor merges a PR that breaks the haddock-
  links check on master, the rolling-issue workflow step would crash
  there, leaving the issue or comment half-created. Wrap both
  addAssignees calls in try/catch and remove assignees from the
  issues.create payload, doing assignment as a separate best-effort
  call so the issue always lands (r3159784547).
Fix broken cross-package Haddock links on hosted docs site
Fixes #601. Cross-package hrefs emitted by cabal haddock-project are
relative paths (e.g. href="../cardano-ledger-api-1.2.3-hash/Foo.html")
that don't resolve on the published site — we only host cardano-api's
own output, not its dependencies, so every cross-package reference
404s by default.

Add scripts/fix-haddock-links.sh and wire it into the github-page
workflow between haddock-project and the artifact upload. The script
replaces each cross-package href with either an absolute URL on the
upstream doc site or a tooltip-annotated unclickable <span>, so the
published site has zero clickable 404s.

Pipeline
  Phase 1  Scan filesystem, symlink versioned directories, fetch the
           CHaP index, grep HTML for cross-package link targets.
  Phase 2  For each discovered target, probe candidate doc-site URLs
           and rewrite links (or mark unclickable if unresolvable).
  Phase 2b Rewrite local re-export pages to point at the defining
           upstream package, using Haddock's "Source" cabal-store link
           as ground truth for which package the type lives in.
  Phase 3  HEAD-validate rewritten URLs; rescue dead ones by probing
           doc-site subdirs (api/, protocols/, framework/) and parent
           modules with #t: fragment reconstruction. What can't be
           rescued becomes an annotated <span>.

Doc-site resolution for CHaP packages — two lookups, first hit wins:
  1. Name-suffix heuristic under *.cardano.intersectmbo.org — strip
     trailing '-token' segments of the package name and HEAD-probe
     each candidate's doc-index.html. Covers cardano-ledger-*,
     plutus-*, ouroboros-*, etc.
  2. Fixed fallback against a small IOG_DOC_BASES list — covers
     packages whose subdomain isn't a suffix of the package name
     (e.g. cardano-base at base.cardano.intersectmbo.org).

Non-CHaP packages (bootlibs like base, bytestring, time) are NOT
linked. Haddock's per-module URL structure doesn't line up cleanly
with Hackage's (src/ source views, -inplace version suffixes) so
Hackage rewrites mostly produce 404s, and readers of cardano-api docs
rarely click into bootlib internals. Rendered as unclickable spans,
no outbound link, no validation noise.

Dead-link CI policy
  Actionable (FAILS CI): a CHaP package the probe couldn't resolve to
  any doc site. Usually a gap in IOG_DOC_BASES — fix by adding the
  package's upstream doc base URL or, if genuinely unpublished, adding
  the package to KNOWN_UNDOCUMENTED.

  Unfixable (does NOT fail CI, logged for visibility): module-level
  404s on otherwise-valid upstream sites where upstream only publishes
  umbrella exposed-modules; packages with no published Haddocks
  anywhere; absolute Hackage URLs that lack a package version. All
  outside this repo to fix.

  Escape hatch FIX_HADDOCK_LINKS_ALLOW_DEAD=1 exits 0 even with
  actionable entries; under GitHub Actions, actionable entries emit
  ::warning:: annotations.

Rolling tracking issue
  Post-merge workflow failures on master open or comment on a single
  rolling issue, tagging the PR opener so the breakage lands on
  someone's board instead of going unnoticed. The Deploy step skips on
  failure, so the published site stays at its last good revision until
  the issue is resolved.

Includes a Herald changelog fragment under .changes/.
Address carbolymer review on PR #1180
- Add changelog fragment with single-line description (no hard wraps in
  the YAML block scalar).
- derive_name_candidates: cap at two-token names. The previous loop
  emitted a single-token URL like cardano.cardano.intersectmbo.org as
  its last candidate. If that subdomain ever resolves (wildcard DNS,
  future deploy, catch-all), probe_site would silently accept it and
  rewrite every cardano-* link to the wrong site. An early break after
  the suffix strip prevents the heuristic from ever emitting a URL
  whose subdomain is a single bare token.
- Add --retry 3 --retry-delay 2 --retry-all-errors to all five curl
  sites. Every probe was previously a single-shot attempt (5s connect,
  10s max). Worst case: Phase 3 validation downgrades a perfectly
  valid rewritten URL into an unclickable <span>, silently shipping a
  regression. Other failure modes: probe_site falling through to a
  wrong candidate, or the CHaP index fetch killing the whole build on
  a CDN hiccup.