---
applyTo: "docs/**"
---

# 設計書共通ルール

## ヘッダー

- `docs/**` 全設計書に frontmatter 必須。必須項目: `spec_runner.node_id` / `kind` / `depends_on` / `maps_to`
- `depends_on`: 文字列配列。依存理由が必要な場合のみオブジェクト形式
- `maps_to`: `src/` / `tests/` / IaC / 設定ファイルを列挙。空にしない。唯一の src 対応（パス推定禁止）
- 設計記録（ADR）は `node_id` と `kind` のみ（決定の記録。実装トレーサビリティに乗らない）
- 拡張項目（`modules` 等）を足す場合も `maps_to` と矛盾させない

```yaml
---
spec_runner:
  node_id: 詳細.ユースケース.注文確定
  kind: detailed_design
  depends_on:
    - 概要.バックエンド.ドメインモデル
    - 詳細.ドメイン.注文
  maps_to:
    - src/application/order/confirm.py
    - src/domain/order/aggregate.py
    - tests/application/order/test_confirm.py
---
```

### node_id 体系

#### 要件定義

| 対象 | node_id 形式 |
|------|-------------|
| 要件定義 | `要件.要件定義` |
| ユビキタス言語辞書 | `要件.ユビキタス言語辞書` |

#### 概要設計

| 対象 | node_id 形式 | 例 |
|------|-------------|-----|
| システム俯瞰図 / システム構成図 | `概要.{名前}` | `概要.システム俯瞰図` |
| バックエンド各設計 | `概要.バックエンド.{名前}` | `概要.バックエンド.ドメインモデル` |
| フロントエンド各設計 | `概要.フロントエンド.{名前}` | `概要.フロントエンド.画面一覧` |
| インターフェース | `概要.インターフェース.{名前}` | `概要.インターフェース.API仕様` |
| 設計記録 | `概要.{対象}.設計記録.{slug}` | `概要.バックエンド.設計記録.0404-注文集約の設計` |

#### 詳細設計

| 対象 | node_id 形式 | 例 |
|------|-------------|-----|
| ドメイン | `詳細.ドメイン.{ドメイン名}` | `詳細.ドメイン.注文` |
| ユースケース | `詳細.ユースケース.{UC名}` | `詳細.ユースケース.注文確定` |
| 共通ポリシー | `詳細.共通.{ポリシー名}` | `詳細.共通.エラーポリシー` |
| DB・マイグレーション | `詳細.データベース.{名前}` | `詳細.データベース.マイグレーション戦略` |
| 外部サービス | `詳細.外部サービス.{名前}` | `詳細.外部サービス.S3` |
| 画面 | `詳細.画面.{画面名}` | `詳細.画面.ログイン` |
| コンポーネント | `詳細.コンポーネント.{名前}` | `詳細.コンポーネント.ボタン` |

## 命名規則

| 対象 | 規則 | 例 |
|------|------|-----|
| `docs/01_要件定義/` | 日本語 | `要件定義.md`, `ユビキタス言語辞書.md` |
| `docs/02_概要設計/01_システム全体設計/` | 日本語 | `システム俯瞰図.md`, `システム構成図.md` |
| `docs/02_概要設計/02_バックエンド/` | 日本語 | `ドメインモデル.md`, `業務ロジック概要.md`, `状態遷移図.md` |
| `docs/02_概要設計/03_フロントエンド/` | 日本語 | `画面一覧.md`, `画面遷移図.md`, `コンポーネント構成.md` |
| `docs/02_概要設計/04_インターフェース設計/` | 日本語 | `API仕様.md`, `外部API連携仕様.md` |
| `docs/02_概要設計/90_ADR/{対象}/` | `mmdd-{日本語タイトル}.md` | `0404-注文集約の設計.md` |
| `docs/03_詳細設計/01_バックエンド/01_ドメイン/` | 日本語 | `注文.md` |
| `docs/03_詳細設計/01_バックエンド/00_共通/` | 日本語 | `エラーポリシー.md` |
| `docs/03_詳細設計/01_バックエンド/02_ユースケース/{カテゴリ名}/` | `UC-{日本語名}.md` | `UC-注文確定.md` |
| `docs/03_詳細設計/01_バックエンド/03_DB・外部サービス/{カテゴリ名}/` | 日本語 | `DB/スキーマ定義.dbml`, `AWS/S3.md` |
| `docs/03_詳細設計/02_フロントエンド/01_画面/{カテゴリ名}/` | 日本語 | `ログイン.md` |
| `docs/03_詳細設計/02_フロントエンド/02_コンポーネント/{カテゴリ名}/` | 日本語 | `ボタン.md` |
| `docs/04_調査資料/{カテゴリ名}/` | 日本語 | `AWS/DynamoDB-キー設計.md` |

## ADR 配置ルール

| 対象 | 配置先 |
|------|--------|
| システム横断 | `docs/02_概要設計/90_ADR/全体/` |
| バックエンド横断 | `docs/02_概要設計/90_ADR/バックエンド/全体/` |
| ドメイン設計 | `docs/02_概要設計/90_ADR/バックエンド/ドメイン/` |
| UC フロー | `docs/02_概要設計/90_ADR/バックエンド/UC/` |
| フロントエンド | `docs/02_概要設計/90_ADR/フロントエンド/` |

## 詳細設計本文フォーマット（ハイブリッド仕様YAML）

対象: 実装と1対1対応する詳細設計（UC・ドメイン・画面・コンポーネント・外部サービス）。frontmatter 直後に ```yaml フェンスを1つだけ置き、本文は全てその中に書く。フェンス外の記述禁止（抽出・lint から漏れる）。例外はファイル末尾の自動生成マーカー区間（`<!-- spec-runner:figure:start/end -->`）のみ — render.js が管理する。手で編集・削除しない。

対象外: 戦略文書（`マイグレーション戦略.md` 等）と `スキーマ定義.dbml` -> 通常の Markdown / DBML。

### ブロック構成（順序固定）

| ブロック | 必須 | 内容 |
|---|---|---|
| `概要` | 必須 | `title` / `purpose`（目的1文。How 禁止）/ `satisfies`（引き受ける REQ-XX の配列） |
| `定数` | 任意 | 設定値・閾値。根拠を行末コメント |
| `公開IF` | 外部から呼ばれるなら必須 | `protocol` / `method` / `path` / `auth` / `成功` / `エラー` |
| `入出力` | 必須 | `inputs` / `outputs` / `exceptions` |
| `状態` | 任意 | 状態一覧・集約構造・`遷移`（from / to / when） |
| `フロー` | 振る舞いがあれば必須 | 処理手順。ループ = `loop`/`body`/`exit`、tx = `tx`/`body` |
| `非機能` | 任意 | 実装を変える制約のみ（冪等性・性能予算等）。願望禁止 |
| `テスト仕様` | 必須 | `T-XX` 一覧 |
| `補足` | 任意 | 自由記述 |

### 要件トレーサビリティ（REQ）

- 要件定義の「受け入れ基準」に `REQ-XX: <状況>のとき、システムは<振る舞い>すること` を1件1行で書く（kind が `requirement` のファイルから収集される）
- 詳細設計は `概要.satisfies: [REQ-XX]` で要件を引き受ける。UC・画面は必須（ユーザー価値の単位）、ドメイン・コンポーネント・外部サービスは該当があれば書く
- lint が双方向に検証: 引き受け先のない REQ（実装漏れ）/ 存在しない REQ への参照

### 記述ルール

- 値の二重記載禁止: 定数値をフロー・テスト仕様に再掲しない。名前で参照
- 曖昧語禁止: 「適切に / 必要に応じて / など / 等 / 柔軟に / できるだけ」を仕様に書かない。条件・範囲を具体化する（lint が検出）
- 定数が config・環境変数経由で実装される場合は行末に `# drift-ok: <経路>` を書く（drift 突合をスキップ。理由なしの drift-ok 禁止）
- ステップ位置参照禁止（「step 3〜4 を繰り返す」NG）。ループは `loop`/`body`/`exit`。ネスト1段まで。超えるなら設計書を分割
- tx 境界は `tx`（理由）/`body`。文章で「同一トランザクション」と書かない
- `exceptions` は1原因1エントリ。フローの `error: <条件> -> <例外型>` で送出点を紐づけ
- `テスト仕様`: `id`/`type`（単体/結合/E2E）/`case`（条件と期待を1文）。例外検証は `covers: [exceptions.<条件>]`。全 exceptions に対応テスト必須
- `type` 語彙: `整数`/`数値`/`文字列`/`真偽`/`日時`/`パス`/`列挙(a|b)`。ドメイン公開操作のみ `操作`
- ドメイン: `入出力` に公開操作、`状態` に集約構造と不変条件
- バリデーション: 独立セクション禁止。各 input の `rule:` に書き、違反は `exceptions` + `error:` + `covers:` で担保
- 画面のインタラクション: step に `on:`（トリガー）/`next:`（遷移先）。順序のない操作イベントも step として列挙可
- 使用コンポーネント一覧表禁止。依存は `depends_on` が正本、本文は `CMP-{番号}` インライン参照のみ

### 公開IF

外部（HTTP・CLI・イベント）から呼ばれる UC は必須。**Router 配線の正本** -> 配線まで実装範囲。

```yaml
公開IF:
  protocol: REST            # REST / GraphQL / CLI / イベント
  method: POST
  path: /api/orders
  auth: 必須(一般ユーザー)   # 不要 / 必須(ロール)
  成功: 201
  エラー:
    - exceptions.在庫が不足 -> 409
```

- `エラー` 各行は `入出力.exceptions` の `cond` を参照（lint が実在検証）
- 概要の `API仕様.md` はパス⇔UC の目次に留める。ステータス・auth の正本は各 UC の `公開IF`

### 図（Mermaid）

- 詳細設計に図を**手で書かない・生成する**。`render.js` が フロー -> flowchart / `状態.遷移` -> stateDiagram を**各設計書の末尾マーカー区間に埋め込む**（hooks で常に最新。仕様を直せば図も追従する）
- 横断図は `docs/_generated/`: `dependencies.md`（依存グラフ）と `dashboard.md`（健康表・要件カバレッジ・警告一覧）
- 俯瞰図（システム構成・画面遷移・ドメイン概念）は概要設計に Mermaid で書く

```yaml
状態:
  - 状態一覧: [下書き, 確定, 出荷済み]
    遷移:
      - { from: 下書き, to: 確定, when: 確定操作が成功 }
```

### 例

```yaml
概要:
  title: UC-ページスクレイピング
  purpose: 事前起動した Chrome 上の縦書きビューアから全ページのスクリーンショットを取得する

定数:
  CDP_URL: "http://127.0.0.1:9222"   # launch_chrome.sh のデバッグポートと一致させる
  PAGE_WAIT_MS: 1500                 # ページ送り後の描画待ち。ビューア描画完了に必要
  MAX_PAGES: 600                     # 暴走防止の上限

入出力:
  inputs:
    - name: start_page
      type: 整数
      default: 1
      desc: 再開時の開始ページ番号
  outputs:
    - name: screenshots
      dest: data/screenshots/page_{page:03d}.png
      desc: 各ページのスクリーンショット
  exceptions:
    - type: ScraperError
      cond: CDP 接続に失敗
    - type: ScraperError
      cond: スクリーンショット撮影・保存に失敗

フロー:
  - step: 1
    do: CDP_URL の Chrome に CDP 接続する
    error: 接続失敗 -> ScraperError
  - step: 2
    do: 「準備ができたら Enter を押してください」と表示し入力を待つ
  - step: 3
    loop: ページごと（start_page から最大 MAX_PAGES 回）
    body:
      - do: 現在ページを撮影し outputs.screenshots の書式で保存する
        error: 撮影・保存失敗 -> ScraperError
      - do: ArrowLeft を送出し PAGE_WAIT_MS 待つ   # 縦書き: 次ページ方向は左
    exit: ArrowLeft 後の page.url が直前と同一なら最終ページとして正常終了

テスト仕様:
  - id: T-01
    type: 結合
    case: 指定ページ数分のスクリーンショットが outputs の命名規則で保存される
  - id: T-02
    type: 結合
    case: ArrowLeft 後に URL が変化しない場合、最終ページと判断して正常終了する
  - id: T-03
    type: 結合
    case: start_page 指定時、そのページ番号からファイルが始まる
  - id: T-04
    type: 結合
    case: CDP 接続失敗時に ScraperError を送出する
    covers: [exceptions.CDP 接続に失敗]
```

### 機械検証（lint / drift）

`scan.js` が Edit / Write のたび hooks で検証。警告は放置せず直す。

**lint（仕様内整合）**: 必須ブロック欠落・順序違反・未知ブロック / 死に定数 / 値の直書き / 例外カバレッジ / 公開IF エラー参照の実在 / T-XX 形式・重複 / 未参照 input / 曖昧語 / タグなしフェンス / REQ カバレッジ（未実装要件・存在しない REQ 参照）/ HTTP method vs 成功ステータス整合（GET→200 / POST→200,201 等）/ 状態遷移の from・to が状態一覧に未定義 / depends_on に存在しない node_id / 複数ノードが同一ファイルを maps_to / 循環 depends_on

**drift（仕様⇔実装。maps_to 先コードを文字列突合）**: 定数（名前 or 値。`# drift-ok:` でスキップ可）/ 公開IF の path・method（Router 未配線検出）/ 例外型 / input 名 / T-XX 双方向 / エラーポリシーとの例外型↔ステータスコード突合（policy-drift）

**unmapped（仕様なきコード）**: どの `maps_to` にも属さない `src/`・`tests/` ファイルを警告。コードには必ず対応する設計書を作る

drift / unmapped が警告止まりの理由: 正当な間接参照・共有ユーティリティがあるため。CI で強制する場合は `scan.js --strict`（テンプレート: `.spec-runner/ci/spec-check.yml`）。

**LLM レビューの担当**: 文字列で判定できない意味論のみ（フロー順序・ループ終了条件・tx 実装・ステータス集中マッピング・ロジック）。

### LLM への受け渡し（部分抽出）

仕様書を丸ごと読ませない。`extract.js` で必要ブロックのみ:

| タスク | ブロック |
|---|---|
| 実装生成 | `概要,定数,公開IF,入出力,状態,フロー,非機能` |
| テスト生成 | `定数,公開IF,入出力,テスト仕様`（結合/E2E ありなら `フロー` も） |
| 整合性レビュー | `公開IF,入出力,フロー,テスト仕様` |

```bash
node .spec-runner/scripts/extract.js <node_id> --blocks 概要,定数,公開IF,入出力,フロー
```

存在しないブロックはスキップされる -> 任意ブロックも常に指定してよい。

## 文書品質

- docs にコードを書かない（コード片・DDL・クラス定義・プロンプト本文）。コードは `src/`・`tests/`
- 設計書本文に設計記録の内容（比較案・採用理由・経緯）を書かない。本文は採用後の仕様のみ
- 設計書の `depends_on` に ADR を含めない。本文・コメントに「ADR xxx 参照」を書かない（設計書は独立して読める）
- 概要設計は「何をするか」のみ。実装詳細を持ち込まない
- 詳細設計はハイブリッド仕様YAMLのブロックで書く
- 設計書とコードは責務1対1。複数責務を1設計書に混ぜない、1責務を分散させない
- HTML タグ・絵文字・記号（✓ ✅ × △ 等）禁止。状態は文字で表現
- `概要.md` のような汎用名禁止。内容を示す名前にする
- 「関連ドキュメント」「スケジュール」セクション禁止（依存は `depends_on`、進捗は設計書の責務外）

## ドメインモデルとデータモデルの分離

| 種別 | 内容 | 置き場所 |
|------|------|---------|
| ドメインモデル | ビジネスルール・集約・値オブジェクト・不変条件 | `01_ドメイン/` |
| データモデル | DB スキーマ・テーブル・カラム・インデックス | `03_DB・外部サービス/DB/` |

相互に持ち込まない。概要設計の `ドメインモデル.md` も概念図であり永続化構造ではない。
