コンテンツにスキップ

GRP-002 循環参照

ドキュメント間の Markdown リンクをグラフとみなして、循環(A → B → C → A のような閉路)が発生していないかを検証します。循環が見つかると error で報告されます。プロジェクトスコープ のルールで、include で読み込んだ全ドキュメントを横断して評価されます。

検出対象は相対パスで .md ファイルを指すリンクのみです。アンカーだけのリンク(#section)や外部 URL は無視されます。

ドキュメント A が B を参照し、B が C を参照し、C が A を参照する、というような循環は、人間が単独のファイルを見ているだけでは絶対に気づけません。整合性のある依存関係を保つには、ドキュメントグラフが DAG(有向非巡回グラフ)であることが望ましく、循環は読者の混乱と更新時の影響範囲の追跡困難を生みます。AI で大量にドキュメントを生成すると、リンクが意図せず双方向になって循環が発生することもあります。このルールはそうした循環を検出します。

フィールド必須説明
filesstring循環検出の対象とするファイルの glob。未指定なら全ドキュメント
excludestring[]グラフから除外するファイルの glob 配列

オプション全体を省略しても動作します。exclude は、目次ファイルや index ファイルのように複数方向のリンクを意図的に持つファイルを除外する用途で使います。

docs/a.md:
# A
See [B](./b.md).
docs/b.md:
# B
See [C](./c.md).
docs/c.md:
# C
See [A](./a.md).

a.md → b.md → c.md → a.md の循環が発生しているので違反になります。

docs/a.md
line 2 error Circular reference detected: docs/a.md -> docs/b.md -> docs/c.md -> docs/a.md GRP-002

循環の中で「最も依存の弱いリンク」 を 1 本切ります。たとえば c.md → a.md のリンクを別の表現に変えます。

docs/c.md:
# C
This module is consumed by upstream documents.
{
"rule": "grp002",
"options": {
"files": "docs/**/*.md",
"exclude": ["docs/index.md", "docs/sitemap.md"]
}
}

exclude で指定したファイルはグラフからノードごと除外されます。それらを介した循環は検出対象外になるので、双方向リンクが必要な目次系ファイルだけに使うのが推奨です。