Skip to content

Commit 86eafed

Browse files
ci(check-links): 把 docs/adr/ 纳入断链检查,带围栏/行内代码判别与只减不增基线 (#6731)
`.github/workflows/check-links.yml` 只扫 content/** 与 README.md,docs/adr/ 从未被检查过 —— 决策记录之间互相引用极密集(多数 `**Builds on**:` 行带 3-10 条相对链接),#5992 修掉的那条死链(0057 指向不存在的 `./0010-metadata-protection.md`)因此长期存活,久到一条 triage 评论把错误 归属继承并重复了一遍。 新增 `scripts/check-adr-links.mjs`(零依赖,`node` 直接跑),在同一条 advisory 车道(check-links.yml)里解析 docs/adr/ 的每一条相对链接目标。 判别机制:提取前先剥掉**围栏代码块与行内代码 span**。ADR-0046 是定义 package-docs 链接约定的那份记录,它按约定举例,故意写了本仓库不存在的 `./crm_lead_guide.md`(第 30 行代码 span、第 163 行 ```md 围栏、第 188 行 `![](…)`)—— 这三处写法正确,该学会读它们的是门,不是让文档迁就门。 ⛔ 按文件 exclude 是被记录在案的陷阱:那会永久遮蔽该记录的 4 条真实互链。 8 条既有死链(全部是 ADR → 源码树、目标已移出本仓库)冻结在 `KNOWN_DEAD_TARGETS` 只减不增基线上,形状与 `check-adr-anchors` 的 `KNOWN_NUMBER_COLLISIONS`、`check:role-word` 一致:新增死链红,基线条目 不再对应死链也红(stale),基线活不过它的理由。lychee 的 `.lycheeignore` 表达不了这一点,而实测把 `docs/adr/**/*.md` 直接加进 lychee glob 会当场 报 8 条错 —— 让一条 advisory 车道从落地那天起长红,就是没人再看的门。 Claude-Session: https://claude.ai/code/session_01F8q5J1MQyocgtNspb15fSn Co-authored-by: Claude <noreply@anthropic.com>
1 parent d5e9f6e commit 86eafed

3 files changed

Lines changed: 529 additions & 0 deletions

File tree

‎.github/workflows/check-links.yml‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ jobs:
3333
- name: Checkout repository
3434
uses: actions/checkout@v7
3535

36+
# ADR cross-link gate (#6592). `docs/adr/` is deliberately NOT added to the
37+
# lychee globs below -- see the ⛔ note there for why -- so the decision
38+
# registry gets its own resolver, in the same advisory lane.
39+
#
40+
# Deliberately `node` and not `pnpm`: the script has zero dependencies, so
41+
# this lane needs no setup-node / corepack / `pnpm install`, and the whole
42+
# advisory job stays a checkout plus two checks. It is also why an author
43+
# can run it locally in any container (`pnpm check:adr-links` when a
44+
# workspace install exists, `node scripts/check-adr-links.mjs` when it does
45+
# not) -- which lychee, installed by the action at CI time, cannot offer.
46+
- name: Check ADR cross-links
47+
run: node scripts/check-adr-links.mjs --self-test && node scripts/check-adr-links.mjs
48+
3649
- name: Check links with lychee
3750
uses: lycheeverse/lychee-action@v2
3851
with:
@@ -55,6 +68,18 @@ jobs:
5568
# suffix that a site route omits. Without this pair the gate cannot go
5669
# green at all: 1286 root-relative links fail as "Cannot resolve
5770
# root-relative link ... provide a root dir".
71+
#
72+
# ⛔ Do NOT add `docs/adr/**/*.md` here. It looks like the one-line fix
73+
# for #6592 and it is not: measured on the pinned lychee 0.24.2, that
74+
# glob reports 8 broken links today, every one a pre-existing ADR →
75+
# source-tree link whose target moved out of this repo. This job would
76+
# be red on every PR from the moment it merged, which is how an
77+
# advisory lane becomes a lane nobody reads (#6028 landed it
78+
# advisory-first specifically to earn a green streak). `docs/adr/` is
79+
# checked by the `Check ADR cross-links` step above instead, which can
80+
# freeze those 8 on a shrink-only baseline and fail on a NEW one --
81+
# something neither `exclude` nor `.lycheeignore` can express, because
82+
# neither ever tells you an entry stopped being needed.
5883
args: >-
5984
--offline
6085
--root-dir ${{ github.workspace }}/content

‎package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"check:skill-frame-freshness": "node scripts/check-skill-frame-freshness.mjs --self-test && node scripts/check-skill-frame-freshness.mjs",
4343
"check:skill-compatibility": "node scripts/check-skill-compatibility-version.mjs --self-test && node scripts/check-skill-compatibility-version.mjs",
4444
"check:adr-anchors": "node scripts/check-adr-anchors.mjs --self-test && node scripts/check-adr-anchors.mjs",
45+
"check:adr-links": "node scripts/check-adr-links.mjs --self-test && node scripts/check-adr-links.mjs",
4546
"check:platform-checklist": "node scripts/checklist-select.mjs --self-test && node scripts/check-platform-checklist.mjs",
4647
"check:org-identifier": "node scripts/check-org-identifier.mjs",
4748
"check:authz-resolver": "node scripts/check-single-authz-resolver.mjs --self-test && node scripts/check-single-authz-resolver.mjs",

0 commit comments

Comments
 (0)