Apr 20, 1-2 PM (53)
Apr 20, 2-3 PM (68)
Apr 20, 3-4 PM (47)
Apr 20, 4-5 PM (41)
Apr 20, 5-6 PM (31)
Apr 20, 6-7 PM (24)
Apr 20, 7-8 PM (10)
Apr 20, 8-9 PM (7)
Apr 20, 9-10 PM (16)
Apr 20, 10-11 PM (28)
Apr 20, 11-12 AM (18)
Apr 21, 12-1 AM (24)
Apr 21, 1-2 AM (5)
Apr 21, 2-3 AM (13)
Apr 21, 3-4 AM (4)
Apr 21, 4-5 AM (3)
Apr 21, 5-6 AM (8)
Apr 21, 6-7 AM (15)
Apr 21, 7-8 AM (44)
Apr 21, 8-9 AM (119)
Apr 21, 9-10 AM (36)
Apr 21, 10-11 AM (35)
Apr 21, 11-12 PM (98)
Apr 21, 12-1 PM (57)
Apr 21, 1-2 PM (71)
Apr 21, 2-3 PM (60)
Apr 21, 3-4 PM (33)
Apr 21, 4-5 PM (31)
Apr 21, 5-6 PM (27)
Apr 21, 6-7 PM (38)
Apr 21, 7-8 PM (35)
Apr 21, 8-9 PM (37)
Apr 21, 9-10 PM (14)
Apr 21, 10-11 PM (34)
Apr 21, 11-12 AM (12)
Apr 22, 12-1 AM (2)
Apr 22, 1-2 AM (3)
Apr 22, 2-3 AM (3)
Apr 22, 3-4 AM (4)
Apr 22, 4-5 AM (3)
Apr 22, 5-6 AM (17)
Apr 22, 6-7 AM (34)
Apr 22, 7-8 AM (21)
Apr 22, 8-9 AM (37)
Apr 22, 9-10 AM (18)
Apr 22, 10-11 AM (47)
Apr 22, 11-12 PM (45)
Apr 22, 12-1 PM (56)
Apr 22, 1-2 PM (64)
Apr 22, 2-3 PM (44)
Apr 22, 3-4 PM (86)
Apr 22, 4-5 PM (46)
Apr 22, 5-6 PM (17)
Apr 22, 6-7 PM (10)
Apr 22, 7-8 PM (18)
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 (65)
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 (12)
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 (4)
Apr 26, 10-11 PM (26)
Apr 26, 11-12 AM (21)
Apr 27, 12-1 AM (6)
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 (46)
Apr 27, 9-10 AM (29)
Apr 27, 10-11 AM (61)
Apr 27, 11-12 PM (76)
Apr 27, 12-1 PM (50)
Apr 27, 1-2 PM (9)
3,950 commits this week Apr 20, 2026 - Apr 27, 2026
Harden fix-haddock-links against several edge cases
Seven fixes from a code review of the script, none of which had
fired in observed CI runs but each of which would surface in a
plausible scenario:

  1. CSS injection idempotency. The previous unconditional
     's|</head>|<style>...</style></head>|' substitution accumulated
     duplicate <style> blocks on every re-run. Add a
     data-dead-link='1' sentinel attribute and gate the substitution
     on /data-dead-link/! so already-injected files are skipped.

  2. Phase 3 grep tolerates no-match. With set -e + pipefail,
     'grep ... | sort -u > FILE' aborted the script when the corpus
     contained no absolute https URLs. Append '|| true' to keep the
     pipeline non-fatal — url_count is checked separately afterwards.

  3. shopt -s nullglob. Empty-glob expansions previously left the
     literal '*/' as the loop variable, which would have inserted '*'
     into SHORT_DIRS / LOCAL_SET. Doesn't trigger on cardano-api but
     the one-line shopt is cheap insurance.

  4. add_unclickable_cmd escapes its title argument against sed
     replacement specials (& \) and the | delimiter. Current callers
     pass package-name-derived strings that can't contain those, but
     defensive escaping protects future callers from breaking the
     emitted sed script.

  5. Explicit error on CHaP fetch failure. Replace the bare
     'curl -sL ... | tar -tz | ...' pipeline with --fail and a
     wrapped if-check, plus a non-empty assertion afterwards, so an
     IOG outage produces a clear error rather than masquerading as
     'everything is non-CHaP'.

  6. Clamp reexport_unresolvable. The previous calculation
     'total - rewritten' could go negative if Python emitted
     duplicate (local_page, anchor, name) rows. Clamp to >= 0.

  7. Pkg extraction tolerates DOC_SUBDIRS in the URL. For
     non-Hackage dead URLs, strip any /api/ /protocols/ /framework/
     segment before extracting the package, so a path like
     .../<pkg>/api/Module.html now yields <pkg> instead of 'api'.

Verified locally: full script runs to exit 0, CSS injection idempotent
under repeated invocation.
testnet: drop tag side from digest-pinned images (Antithesis parser)
Antithesis's image puller rejects `name:tag@sha256:digest` with
"Invalid image name: cannot be empty or contain invalid character"
(verified via run https://github.com/cardano-foundation/cardano-node-antithesis/actions/runs/24998978617).

Switch to canonical OCI digest-only form `name@sha256:digest`. Identical
content guarantee, accepted by Antithesis.

Update push-cardano_node_master_images.sh to skip entries that have no
tag after sanitization — digest-only pins refer to images that already
exist in the registry by definition; there is nothing to rebuild.
chore(deps): Bump webiny/action-conventional-commits from 1.3.1 to 1.4.2
Bumps [webiny/action-conventional-commits](https://github.com/webiny/action-conventional-commits) from 1.3.1 to 1.4.2.
- [Release notes](https://github.com/webiny/action-conventional-commits/releases)
- [Commits](https://github.com/webiny/action-conventional-commits/compare/v1.3.1...v1.4.2)

---
updated-dependencies:
- dependency-name: webiny/action-conventional-commits
  dependency-version: 1.4.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
chore(deps): Bump github.com/blinklabs-io/gouroboros
Bumps [github.com/blinklabs-io/gouroboros](https://github.com/blinklabs-io/gouroboros) from 0.153.1 to 0.165.3.
- [Release notes](https://github.com/blinklabs-io/gouroboros/releases)
- [Changelog](https://github.com/blinklabs-io/gouroboros/blob/main/RELEASE_NOTES.md)
- [Commits](https://github.com/blinklabs-io/gouroboros/compare/v0.153.1...v0.165.3)

---
updated-dependencies:
- dependency-name: github.com/blinklabs-io/gouroboros
  dependency-version: 0.165.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
testnet: vendor Amaru cluster from pragma-org/amaru
Sourced from pragma-org/amaru@d44d84cd9c7a, path docker/testnet.
Authored upstream by Arnaud Bailly. Pin SHA recorded in
testnets/cardano_amaru/.amaru-sha for traceability.

Stack provides 5 cardano-node BPs (10.5.3) in a ring + 2 amaru nodes
bootstrapped from a synthesised chain DB. Reuses existing
cardano-foundation/cardano-node-antithesis sidecar and tracer-sidecar
images.

Vendored as-is; not yet wired into publish-images, justfile, or
Antithesis dispatch — separate follow-up commits.

Refs #72