lychee.toml
Rama main · réplica de lectura del repositorio original.
# Lychee link checker config — used by .github/workflows/docs-quality.yml
exclude_path = [
".claude/worktrees",
"node_modules",
".git",
"packages/docs/dist",
"packages/docs/.astro",
]
exclude = [
# Asciinema casts get uploaded post-merge; skip until the ID exists
"asciinema\\.org/a/<id>",
# localhost references in code examples
"localhost",
"127\\.0\\.0\\.1",
# GitHub Releases anchors that are page-internal
"github\\.com/.*/releases/tag",
# release-please CHANGELOG compare links — the higher tag is only created
# by the release job AFTER the release PR merges, so the link 404s while
# the PR is open. Resolves automatically post-merge.
"github\\.com/nimbus-agent/Nimbus/compare/v",
# External hosts that block scripted user-agents or rate-limit aggressively
# from GitHub-hosted runner egress. Verified live in browsers; the failures
# are infrastructure noise, not broken links.
"npmjs\\.com", # 403 to non-browser UAs
"canva\\.com", # 403 to non-browser UAs
"opengraph\\.xyz", # aggressive 429 rate limit
"tauri\\.app", # intermittent connection failures from runners
"conventionalcommits\\.org", # intermittent TCP RST from GH runner egress
"asciinema\\.org/?$", # homepage times out from runner egress; verified live (200)
"asciinema\\.org/a/", # cast pages also time out under load from runner egress; verified live (200)
"nimbus-agent\\.dev", # exclude until PR 1 DNS propagates
"glama\\.ai", # 525/403 to scripted UAs due to Cloudflare
# 403 from GitHub runner egress only. Checked rather than assumed: from a dev
# machine it returns 200 to BOTH a browser UA and curl's default UA, so this is
# origin/IP-based blocking, not the scripted-UA kind the entries above describe.
# Pre-existing link (the Ramp connector CHANGELOG entry), unrelated to the PR
# that had to exclude it.
"ramp\\.com",
# github-action-benchmark dashboard on the perf-data orphan branch — the branch
# and dev/bench dir are created by the first post-merge push, so the link 404s
# while the PR documenting it is open. Resolves automatically post-merge.
"github\\.com/nimbus-agent/Nimbus/tree/perf-data",
# open-vsx.org's signed-in settings pages (cited in docs/ci-secrets.md and
# docs/credential-hygiene.md) answer 503 intermittently — measured 2026-09-17 from a
# dev machine, not only runner egress: 3 of 6 samples 503 on `/user-settings/tokens`
# while `/extension/...` pages returned 200 on all 6. lychee does not retry a
# rejected status, so both passes failed in three runs across two PRs that day. Scoped to
# `/user-settings/` so the public open-vsx.org links stay checked.
"open-vsx\\.org/user-settings/",
]
# 202 Accepted is a 2xx success — figma.com's homepage returns it to scripted UAs,
# which lychee otherwise rejects (the long-standing intermittent figma.com flake).
accept = ["200", "202", "203", "204", "206", "301", "302", "304"]
max_redirects = 5
timeout = 30
# CORRECTION (supersedes the claim this comment used to make): `max_retries` and
# `retry_wait_time` DO NOT apply to a rejected status code. Measured against a local
# server that counts requests — a 504 and a 503 were each fetched exactly ONCE, while
# a dropped connection was fetched FOUR times (1 + 3 retries). lychee retries
# TRANSPORT errors only; a response that arrives and fails the `accept` list is final.
#
# So these two settings do nothing for the recurring github.com 504, which was the
# reason given for adding `retry_wait_time` in #1200. They are kept because they are
# still correct for genuine transport flakes (connection reset, TLS hiccup), which do
# occur from runner egress — but they are not the 504 mitigation.
#
# The 504 is handled where it can be: `scripts/check-links.sh` (used by both
# `audit:links` and the workflow step) caches successes with `--cache` and retries the
# run once, so the retry re-checks ONLY what failed — verified: 2 OK URLs fetched once
# across two passes, the 504 URL fetched twice. A genuinely dead link still fails both
# passes and the gate still goes red, which accepting 5xx as success would not
# preserve.
max_retries = 3
retry_wait_time = 2
# Per-HOST, not global: almost every link here is github.com, so the run was
# opening far more simultaneous connections to one host than it needs to. This
# caps that without throttling other hosts.
#
# It is not free. Measured locally over the real link set (1,313 links, 845
# unique), one run each: 111s before, 127s after — roughly +15%, some of which
# is network variance. That is judged worth it against a gate that has produced
# two false failures in a day, each costing a re-run and eroding trust in the
# job. Raise this number if the run time starts to matter more than the flake.
host_concurrency = 8