Home / Input Output / cardano-api
Apr 23, 11-12 AM (0)
Apr 24, 12-1 AM (0)
Apr 24, 1-2 AM (0)
Apr 24, 2-3 AM (0)
Apr 24, 3-4 AM (0)
Apr 24, 4-5 AM (0)
Apr 24, 5-6 AM (0)
Apr 24, 6-7 AM (0)
Apr 24, 7-8 AM (0)
Apr 24, 8-9 AM (2)
Apr 24, 9-10 AM (0)
Apr 24, 10-11 AM (0)
Apr 24, 11-12 PM (0)
Apr 24, 12-1 PM (0)
Apr 24, 1-2 PM (0)
Apr 24, 2-3 PM (0)
Apr 24, 3-4 PM (0)
Apr 24, 4-5 PM (0)
Apr 24, 5-6 PM (0)
Apr 24, 6-7 PM (0)
Apr 24, 7-8 PM (0)
Apr 24, 8-9 PM (0)
Apr 24, 9-10 PM (3)
Apr 24, 10-11 PM (0)
Apr 24, 11-12 AM (0)
Apr 25, 12-1 AM (0)
Apr 25, 1-2 AM (0)
Apr 25, 2-3 AM (0)
Apr 25, 3-4 AM (0)
Apr 25, 4-5 AM (0)
Apr 25, 5-6 AM (0)
Apr 25, 6-7 AM (0)
Apr 25, 7-8 AM (0)
Apr 25, 8-9 AM (0)
Apr 25, 9-10 AM (0)
Apr 25, 10-11 AM (0)
Apr 25, 11-12 PM (0)
Apr 25, 12-1 PM (0)
Apr 25, 1-2 PM (0)
Apr 25, 2-3 PM (0)
Apr 25, 3-4 PM (0)
Apr 25, 4-5 PM (0)
Apr 25, 5-6 PM (0)
Apr 25, 6-7 PM (0)
Apr 25, 7-8 PM (0)
Apr 25, 8-9 PM (0)
Apr 25, 9-10 PM (0)
Apr 25, 10-11 PM (0)
Apr 25, 11-12 AM (0)
Apr 26, 12-1 AM (0)
Apr 26, 1-2 AM (0)
Apr 26, 2-3 AM (0)
Apr 26, 3-4 AM (0)
Apr 26, 4-5 AM (0)
Apr 26, 5-6 AM (0)
Apr 26, 6-7 AM (0)
Apr 26, 7-8 AM (0)
Apr 26, 8-9 AM (0)
Apr 26, 9-10 AM (0)
Apr 26, 10-11 AM (0)
Apr 26, 11-12 PM (0)
Apr 26, 12-1 PM (0)
Apr 26, 1-2 PM (0)
Apr 26, 2-3 PM (0)
Apr 26, 3-4 PM (0)
Apr 26, 4-5 PM (0)
Apr 26, 5-6 PM (0)
Apr 26, 6-7 PM (0)
Apr 26, 7-8 PM (0)
Apr 26, 8-9 PM (0)
Apr 26, 9-10 PM (0)
Apr 26, 10-11 PM (0)
Apr 26, 11-12 AM (0)
Apr 27, 12-1 AM (0)
Apr 27, 1-2 AM (0)
Apr 27, 2-3 AM (0)
Apr 27, 3-4 AM (0)
Apr 27, 4-5 AM (0)
Apr 27, 5-6 AM (0)
Apr 27, 6-7 AM (0)
Apr 27, 7-8 AM (0)
Apr 27, 8-9 AM (1)
Apr 27, 9-10 AM (0)
Apr 27, 10-11 AM (0)
Apr 27, 11-12 PM (0)
Apr 27, 12-1 PM (0)
Apr 27, 1-2 PM (1)
Apr 27, 2-3 PM (0)
Apr 27, 3-4 PM (1)
Apr 27, 4-5 PM (0)
Apr 27, 5-6 PM (0)
Apr 27, 6-7 PM (1)
Apr 27, 7-8 PM (2)
Apr 27, 8-9 PM (0)
Apr 27, 9-10 PM (0)
Apr 27, 10-11 PM (0)
Apr 27, 11-12 AM (0)
Apr 28, 12-1 AM (0)
Apr 28, 1-2 AM (0)
Apr 28, 2-3 AM (0)
Apr 28, 3-4 AM (0)
Apr 28, 4-5 AM (0)
Apr 28, 5-6 AM (0)
Apr 28, 6-7 AM (0)
Apr 28, 7-8 AM (0)
Apr 28, 8-9 AM (1)
Apr 28, 9-10 AM (0)
Apr 28, 10-11 AM (0)
Apr 28, 11-12 PM (0)
Apr 28, 12-1 PM (2)
Apr 28, 1-2 PM (0)
Apr 28, 2-3 PM (0)
Apr 28, 3-4 PM (0)
Apr 28, 4-5 PM (0)
Apr 28, 5-6 PM (0)
Apr 28, 6-7 PM (0)
Apr 28, 7-8 PM (0)
Apr 28, 8-9 PM (0)
Apr 28, 9-10 PM (0)
Apr 28, 10-11 PM (0)
Apr 28, 11-12 AM (0)
Apr 29, 12-1 AM (0)
Apr 29, 1-2 AM (0)
Apr 29, 2-3 AM (0)
Apr 29, 3-4 AM (0)
Apr 29, 4-5 AM (0)
Apr 29, 5-6 AM (0)
Apr 29, 6-7 AM (1)
Apr 29, 7-8 AM (0)
Apr 29, 8-9 AM (0)
Apr 29, 9-10 AM (0)
Apr 29, 10-11 AM (0)
Apr 29, 11-12 PM (0)
Apr 29, 12-1 PM (0)
Apr 29, 1-2 PM (0)
Apr 29, 2-3 PM (0)
Apr 29, 3-4 PM (0)
Apr 29, 4-5 PM (1)
Apr 29, 5-6 PM (1)
Apr 29, 6-7 PM (0)
Apr 29, 7-8 PM (0)
Apr 29, 8-9 PM (2)
Apr 29, 9-10 PM (0)
Apr 29, 10-11 PM (0)
Apr 29, 11-12 AM (0)
Apr 30, 12-1 AM (1)
Apr 30, 1-2 AM (0)
Apr 30, 2-3 AM (0)
Apr 30, 3-4 AM (0)
Apr 30, 4-5 AM (0)
Apr 30, 5-6 AM (0)
Apr 30, 6-7 AM (0)
Apr 30, 7-8 AM (0)
Apr 30, 8-9 AM (1)
Apr 30, 9-10 AM (1)
Apr 30, 10-11 AM (0)
Apr 30, 11-12 PM (1)
Apr 30, 12-1 PM (2)
Apr 30, 1-2 PM (1)
Apr 30, 2-3 PM (0)
Apr 30, 3-4 PM (0)
Apr 30, 4-5 PM (0)
Apr 30, 5-6 PM (0)
Apr 30, 6-7 PM (3)
Apr 30, 7-8 PM (0)
Apr 30, 8-9 PM (0)
Apr 30, 9-10 PM (0)
Apr 30, 10-11 PM (0)
Apr 30, 11-12 AM (0)
29 commits this week Apr 24, 2026 - May 01, 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/.
Track haddock dead-link CI failures in a rolling issue
When the haddock-links check fails on master, open (or comment on)
a single tracking issue identified by the marker label
'haddock-ci-failure', @-mentioning the breaker — sourced from the
master commit's associated PR via
listPullRequestsAssociatedWithCommit, which handles squash merges.

The issue body documents the fix recipe (add the package's doc base
URL to IOG_DOC_BASES, or add the package to KNOWN_UNDOCUMENTED).
Each failure appends a comment with the run URL so the audit trail
of consecutive breakages is visible in one place.

Add an id to the haddock-links step so the new tag-breaker step can
gate on its specific outcome (failure() && steps.<id>.outcome ==
'failure'), avoiding spurious issue creation on unrelated failures
(cabal build, nix shell, network glitch in haddock-project, etc.).
Track haddock dead-link CI failures in a rolling issue
When the haddock-links check fails on master, open (or comment on)
a single tracking issue identified by the marker label
'haddock-ci-failure', @-mentioning the breaker — sourced from the
master commit's associated PR via
listPullRequestsAssociatedWithCommit, which handles squash merges.

The issue body documents the fix recipe (add the package's doc base
URL to IOG_DOC_BASES, or add the package to KNOWN_UNDOCUMENTED).
Each failure appends a comment with the run URL so the audit trail
of consecutive breakages is visible in one place.

Add an id to the haddock-links step so the new tag-breaker step can
gate on its specific outcome (failure() && steps.<id>.outcome ==
'failure'), avoiding spurious issue creation on unrelated failures
(cabal build, nix shell, network glitch in haddock-project, etc.).
Add dead-link CI policy and document the design in a preamble
Partition dead links into two buckets with different CI treatment:

  Actionable (FAILS CI) — CHaP packages the probe couldn't resolve
    to any doc site. Usually a gap in IOG_DOC_BASES. Fix by adding
    the doc site, or by adding the package to KNOWN_UNDOCUMENTED
    if it genuinely has no published Haddocks anywhere.

  Unfixable (logged for visibility, does NOT fail CI) — three sub-
    causes, all outside this repo:
      a. Module-level 404s on otherwise-valid upstream sites.
         Empirically the cause is upstream publishing only their
         umbrella "exposed-modules" (e.g. Cardano-Binary.html) while
         Haddock generates hrefs to the defining sub-module (e.g.
         Cardano-Binary-FromCBOR.html).
      b. Packages in KNOWN_UNDOCUMENTED with no published Haddocks
         anywhere (currently kes-agent and kes-agent-crypto —
         verified no gh-pages branch, no CloudFront deployment).
      c. Haddock-emitted versionless Hackage URLs that Hackage's
         routing doesn't accept.

Add typed-protocols to IOG_DOC_BASES: its Haddocks are published at
input-output-hk.github.io/typed-protocols, which the heuristic now
reaches via the fallback list.

In GitHub Actions, actionable entries emit ::warning:: annotations so
they surface in the job UI; unfixable entries are plain log lines so
they don't flood the annotations panel. Env escape
FIX_HADDOCK_LINKS_ALLOW_DEAD=1 forces exit 0 regardless.

Rewrite the preamble to summarise the pipeline, the doc-site
resolution strategy, the rationale for skipping non-CHaP packages,
and the two-bucket CI policy with empirical justification.