docs: address Codex review of the RFC reorg

- Fix two root-AGENTS.md cross-links that the depth bump left pointing at the
  new docs/AGENTS.md instead of the root file they cite (capability-seams,
  optional-code-mode). These resolved on disk so verify-md-links passed — the
  gate checks existence, not which file you meant; corrected to ../../../.
- Broaden verify-md-links scope to .agents/skills/**/*.md: this PR rewrote the
  dsh-code-review skill's links into the RFC tree, but the skill dir was outside
  the gate, so a broken skill link would have passed silently.
- Percent-decode the path component before the existence check, so a valid
  encoded relative target (My%20File.md) is not falsely reported broken; a
  malformed escape (%zz) is reported broken rather than crashing the gate.
- Drop the merged property-testing RFC's "nightly CI job 100x" claim: that line
  came from the original proposal, not the accepted decision, and CI has only
  push/pull_request triggers — note it as possible future work instead.

doc-sync (incl. verify-md-links over 58 files), doc-typecheck, lint pass.
This commit is contained in:
Tianyi Cui
2026-06-18 02:41:19 +08:00
parent 7c400e9c02
commit 27f5f84e3b
5 changed files with 40 additions and 12 deletions

View File

@@ -20,10 +20,13 @@
* resolved against the linking file's directory, and the result must exist on
* disk. This is checker, not fixer: it reports and never rewrites.
*
* Scope mirrors the other doc-sync gates plus the two AGENTS.md files:
* README.md, docs/** /*.md, packages/* /README.md, AGENTS.md, packages/AGENTS.md.
* The root and packages/ CLAUDE.md are symlinks to the AGENTS.md files, so they
* are deduped by real path.
* Scope is the other doc-sync gates' set plus the two AGENTS.md files AND the
* repo-authored agent-skill Markdown under `.agents/skills/` — those skill
* files cross-link into the docs tree (e.g. the dsh-code-review skill cites the
* RFC index), so a rename must not silently break them either: README.md,
* docs/** /*.md, packages/* /README.md, AGENTS.md, packages/AGENTS.md,
* .agents/skills/** /*.md. The root and packages/ CLAUDE.md are symlinks to the
* AGENTS.md files, so they are deduped by real path.
*
* Run: `tsx scripts/verify-md-links.ts`.
*/
@@ -38,8 +41,18 @@ import type { Nodes } from 'mdast'
const root = resolve(import.meta.dirname, '..')
/** Files to check: doc-typecheck's scope plus the AGENTS.md pair. */
const PATTERNS = ['README.md', 'docs/**/*.md', 'packages/*/README.md', 'AGENTS.md', 'packages/AGENTS.md']
/**
* Files to check: doc-typecheck's scope, the AGENTS.md pair, and repo-authored
* agent-skill Markdown (which this repo's own docs reorg rewrites links in).
*/
const PATTERNS = [
'README.md',
'docs/**/*.md',
'packages/*/README.md',
'AGENTS.md',
'packages/AGENTS.md',
'.agents/skills/**/*.md',
]
/** A broken relative link: a target path that does not resolve to a file. */
interface Violation {
@@ -62,9 +75,24 @@ function isExternalOrAnchor(url: string): boolean {
return /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(url)
}
/** Strip the `#fragment` and `?query` from a link target, leaving the path. */
/**
* Strip the `#fragment` and `?query` from a link target, then percent-decode
* the remaining path so an encoded target (`My%20File.md`, `READ%4DE.md`)
* probes the real filename on disk, the way a Markdown renderer resolves it. A
* malformed escape (`%zz`) makes `decodeURIComponent` throw; we keep the raw
* path in that case so the link is reported as broken (a `%zz` target is not a
* file anyone meant to link) rather than crashing the gate.
*/
function pathPart(url: string): string {
return url.replace(/[#?].*$/, '')
const raw = url.replace(/[#?].*$/, '')
try {
return decodeURIComponent(raw)
} catch {
// decodeURIComponent throws only on a malformed percent-escape; the raw
// string is then a path no renderer resolves, so fall through to the
// existence check, which reports it broken.
return raw
}
}
/** Find every broken relative cross-link in one Markdown file via its AST. */