根拠 ADR: ADR-0051 — docs/_config.json nav 未登録の .md ファイル検出 lint を追加

1. このガイドが扱う問題

新規 .mddocs/ 配下に追加した際、docs/_config.json の nav 配列に登録し忘れると Cloudflare Pages 上で 404 状態のまま放置 される (PR #796/#827 で実際に 2 日間 404 発生)。

これを CI で機械的に検出するのが scripts/docs-nav-lint.mjs。3 ルールで lint:

Rule種類内容
R1orphan-mddocs/**/*.md のうち _config.json の nav 配列に未登録
R2broken-nav-entry_config.jsonfile: が指す実体ファイルが存在しない
R3duplicate-nav-entry同一 file が複数 nav エントリに登録されている

2. ローカル実行

# 通常実行 (R1=WARN, R2/R3=FAIL)
npm run docs:lint

# Grace period 終了後 (2 週間後): R1 も FAIL になるモード
node scripts/docs-nav-lint.mjs --strict

# 現存 orphan を allowlist に一括追加 (緊急時の current-state freeze)
node scripts/docs-nav-lint.mjs --add-current-orphans

Exit code: 0 = pass, 1 = fail, 2 = usage error。

3. CI 実行

.github/workflows/docs-nav-lint.yml で PR + main push 時に自動実行。 GitHub PR の status check 欄に docs-nav-lint が緑/黄/赤で表示される。

Grace period (移行期間 2 週間): env.STRICT: 'false' で R1 を WARN 扱い (PR ブロックなし)。 2026-06-01 以降に STRICT: 'true' へ切替予定 → R1 も FAIL 化。

4. よくあるエラーと対応

4.1 [R1 orphan-md] xxx.md is not registered in docs/_config.json nav array

新規 .md を追加したのに nav に未登録。対応はどちらか:

A. nav に登録する (デフォルト推奨)

docs/_config.json の対象 group の "pages" 配列に追記:

{
  "file": "your/new/file.md",
  "title": "X.Y.Z タイトル"
}

title のプレフィックス (F.X.NN / A.NN / E.X.NN 等) は周辺エントリに合わせる。

B. allowlist に追加 (nav 対象外と判断した場合)

.docs-nav-lint-allowlist.jsonfiles 配列に追加:

{
  "files": [
    "your/new/file.md"
  ],
  "patterns": []
}

ディレクトリ単位で除外したい場合は patterns に正規表現:

{
  "patterns": [
    "^your/dir/.+\\.md$"
  ]
}

4.2 [R2 broken-nav-entry] "xxx.md" does not exist on disk

nav に登録された file が実在しない (リネーム・削除漏れ)。 docs/_config.json を修正して該当エントリを削除 or path 訂正。

4.3 [R3 duplicate-nav-entry] "xxx.md" appears N times

同じ file が複数 nav エントリに登録。docs/_config.json を修正していずれか 1 つに統一。

5. PR ブロック時の救済 ([skip-nav-lint] ラベル)

緊急時に lint を bypass するには PR に [skip-nav-lint] ラベルを付与:

gh pr edit <PR番号> --add-label "[skip-nav-lint]"

workflow の if: 条件でジョブがスキップされる (ADR-0051 §7 救済手順)。 bypass 利用後は必ず後続 PR で根本対応すること (allowlist 追加 or nav 登録)。

6. allowlist のメンテナンス

  • 個別 file 追記: 上記 §4.1.B 参照
  • pattern 追記: ディレクトリ全体を除外する場合 (例: daily_log/ 配下は週次で増えるため pattern 化済)
  • 上限 30 件目安: allowlist が肥大化する = 「nav 登録すべきだが運用上できないファイル群」増加 = 設計上の歪み (ADR-0051 §8 負債化リスク)
  • 上限超えたら _config.json の group 構造そのものを見直し起案

7. 撤退条件モニタリング

月初に以下を実行し、docs-nav-lint workflow の failure 件数を集計:

gh run list --workflow=docs-nav-lint.yml --status=failure \
  --created-after=$(date -v-1m +%Y-%m-%d) --json conclusion \
  | jq 'length'

5 件超を 2 ヶ月連続 → R1 を WARN-only に格下げ判断 (ADR-0051 §7)。

: 上記コマンドは BSD date (macOS) 構文。Linux/CI で実行する場合は date --date='1 month ago' +%Y-%m-%d に置換。

8. CI 撤去手順 (撤退判断後)

  • .github/workflows/docs-nav-lint.yml.yml.disabled にリネーム (1 コミット)
  • npm run docs:lint は package.json に残置 (ローカル任意実行のみ可)
  • 撤退時の最終 PR にレビュアー sign-off 必須 (撤退根拠の記録保持)

9. 関連ドキュメント

  • ADR-0051: docs/adr/0051-add-lint-for-unregistered-md-files-in-docs-config-nav.md
  • 設定ファイル: docs/_config.json / .docs-nav-lint-allowlist.json
  • 関連 ADR: ADR-0042 (Prompt Lifecycle 管理 — 同じ「SSoT + 機械チェック + 運用ガード」パターン)