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

# 設計書共通ルール

## ヘッダー

- `docs/**` 全設計書に frontmatter 必須。必須項目: `spec_runner.node_id` / `depends_on`
- `maps_to` は `detailed_design`（`docs/03_`）のみ。要件定義（`docs/01_`）・概要設計（`docs/02_`）には書かない（実装ファイルに直接対応しないため）
- `kind` は不要。`docs/` のパスから自動導出（`01_` → requirement / `02_` → overview_design / `03_/*/00_共通/` → common_policy / `03_` → detailed_design）
- `depends_on`: 文字列配列。依存理由が必要な場合のみオブジェクト形式
- 既存フォルダと異なる必須ブロック構成が必要な新フォルダを作る場合、`architecture.yaml` の `block_config:` にエントリを追加する（スキップすると全フォルダに同じ必須ブロックが適用される）:
  ```yaml
  block_config:
    - path: docs/03_詳細設計/02_フロントエンド/03_ライブラリ/
      required: [概要, テスト仕様]
      optional: [定数, 入出力, フロー, 非機能, 補足]
  ```
- `shared_maps_to`: 複数 UC が共用するファイル（bundled router 等）を列挙する任意フィールド
  - `maps_to` との違い: `duplicate-maps_to` チェック対象外（複数 UC が同じファイルを指定可）
  - drift チェックは有効（endpoint-drift の path/method 突合に使われる）
  - unmapped チェックにも含まれる（仕様なきコード扱いにならない）
- `maps_to`: `src/` / `tests/` / IaC / 設定ファイルを列挙。空にしない。唯一の src 対応（パス推定禁止）。**10件を超える場合は設計書の分割を検討する**（`large-uc` が警告）
  - 日本語をパスに含めない。docs のフォルダ名（`共通` 等の日本語カテゴリ）からパスを推定しない
  - `architecture.yaml` の `folder_structure` を基準にパスを決める。コードが未作成の場合はユーザーに確認してから書く
- 設計記録（ADR）は `node_id` のみ（決定の記録。実装トレーサビリティに乗らない）
- 拡張項目（`modules` 等）を足す場合も `maps_to` と矛盾させない

```yaml
---
spec_runner:
  node_id: 詳細.ユースケース.注文確定
  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名}` | `詳細.ユースケース.注文確定` |
| 共通ポリシー | `詳細.共通.{ポリシー名}` | `詳細.共通.エラーポリシー` |
| 外部サービス | `詳細.外部サービス.{名前}` | `詳細.外部サービス.S3` |
| 画面 | `詳細.画面.{画面名}` | `詳細.画面.ログイン` |
| コンポーネント | `詳細.コンポーネント.{名前}` | `詳細.コンポーネント.ボタン` |

## 命名規則

1ファイル・1フォルダが肥大化したら責務ごとにカテゴリ分割してよい（`{カテゴリ名}/` は表中で明示した箇所に限らず、どの `docs/` フォルダにも適用できる一般原則）。基準は `docs/` に限らず `src/`・`tests/` にも同じ判断を使う。分割単位は責務。ファイル数・行数の固定閾値では機械的に判断しない。

| 対象 | 規則 | 例 |
|------|------|-----|
| `docs/01_要件定義/`（肥大化時は `{カテゴリ名}/要件定義.md` に分割可） | 日本語 | `要件定義.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`（実装が `Button.tsx` でも日本語概念名） |
| `docs/03_詳細設計/02_フロントエンド/03_ライブラリ/` | 日本語 | `ストア.md`, `APIクライアント.md` |
| `docs/04_調査資料/{カテゴリ名}/` | 日本語 | `AWS/DynamoDB-キー設計.md` |

設計書名は実装ファイル名に合わせない。`maps_to` が紐づけを担保するので、設計書名は常に日本語の概念名にする。

## ADR 配置ルール

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

## 詳細設計本文フォーマット（構造化 Markdown）

対象: 実装と1対1対応する詳細設計（UC・ドメイン・画面・コンポーネント・外部サービス）。本文は通常の Markdown で書く。**H2 見出し（`## ブロック名`）がブロック、表が構造化データ、番号付きリストがフロー**。この構造をアンカーに scan.js が機械検証する。見出し名・表の列名は下記の語彙に固定（変えると検証から漏れる）。

ファイル末尾の自動生成マーカー区間（`<!-- spec-runner:figure:start/end -->`）は render.js が管理する。手で編集・削除しない。

対象外: `スキーマ定義.dbml` -> 通常の DBML。

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

| ブロック | 必須 | 書き方 |
|---|---|---|
| `概要` | 必須 | `## 概要` セクション。箇条書きで `- **目的**:`（1文。How 禁止）/ `- **使用するドメイン**:` / `- **トリガー**:` / `- **事前条件**:` / `- **事後条件**:` を書く。名称 = H1 見出し。設計判断・方式選定の理由は書かない（`非機能` か ADR へ） |
| `公開インターフェース` | 外部から呼ばれるなら必須 | 表 `項目 / 値`（プロトコル / メソッド / パス / 認証 / 成功）。失敗時の対応は書かない（`例外` の `公開結果` 列が正本） |
| `入出力` | 必須 | `### 入力` / `### 出力` の小見出しで分割し、それぞれ表 `名前 / 型 / 既定値 / 検証 / 説明`（列順は全ブロックで統一する）。出力の表は 型・既定値・検証 が空になりやすいが、それでよい。出力先が重要な情報なら 説明 の先頭に書く（例: 「出力先: HTTPレスポンスヘッダー。会話ID」） |
| `例外` | 例外があれば必須 | バックエンド（UC・ドメイン・外部サービス等、実装に例外クラスが実在する設計書）は表 `例外型 / 発生条件 / 表示文言`。`公開インターフェース` を持つ設計書（UC 等）は `公開結果` 列を足す: この例外を外部にどう見せるか（HTTPステータスコード、または「SSE error イベント」等の自由記述。公開しない内部例外は空）。画面設計書は例外クラスが実在しないため `例外型` 列を持たず、表 `方式 / 発生条件 / 内容`（列順固定。`方式` が先頭）。`方式` は列挙(アラート表示｜画面遷移｜無言)。`内容` の意味は `方式` に応じて変わる（アラート表示: 画面に出す文言。実装コードにそのまま現れる想定でdrift突合の対象／画面遷移: 遷移先の画面名。業務語で書くためURLパス等の実装値と文字列一致せずdrift対象外／無言: 空でよい。drift対象外）。ドメイン・コンポーネントのように公開インターフェースを持たない設計書は `公開結果` 不要 |
| `定数` | 任意 | 表 `名前 / 値 / 根拠`。根拠は必須（なぜこの値か）。主に `フロー` から参照される実装パラメータなので `フロー` の直前に置く |
| `状態` | 任意 | `状態一覧:` 行 + 遷移の表 `元 / 先 / 条件`。集約構造・不変条件は地の文 |
| `フロー` | 振る舞いがあれば必須 | 見出しは `## 主要フロー` でも可。番号付きリスト。各手順 = `N. **要点** — 詳細`。章立ては `### 章名` |
| `判断条件` | 任意 | 表 `判断ポイント / 条件 / アクション`。フローの分岐が複雑なとき条件を一覧化する |
| `非機能` | 任意 | 箇条書き。実装を変える制約のみ（冪等性・性能予算等）。願望禁止 |
| `テスト仕様` | 必須 | 見出しは `## テスト一覧` でも可。表 `ID / レベル / 種別 / テスト名 / 備考`（レベル = 単体 / 結合 / E2E、種別 = 正常系 / 異常系 / 境界値。長文の テスト名・備考 は表の右端に置く。前提条件・期待結果を別列にしてもよい） |
| `補足` | 任意 | 実装者向けの脚注（自由記述。抽出は実装生成にのみ同梱）。テスト・レビューが判断に使う事実や検証されたい値は置かない（テスト仕様・非機能・定数・入出力へ） |

見出しの別名（`主要フロー` → フロー / `テスト一覧` → テスト仕様 / `エラー` → 例外）はツールが正規化する。extract.js には正規名を渡す。

### 記述ルール

- 値の二重記載禁止: 定数値をフロー・テスト仕様に再掲しない。名前で参照
- 太字はアンカーにのみ使う: フロー手順の `**要点**` / ラベル箇条書きのラベル（`- **目的**: 本文`。概要・非機能・補足で使う）/ ブロック内のグルーピング行（テスト一覧のカテゴリ等）。表のセル内と地の文の強調には使わない
- ラベル箇条書き（概要・非機能・補足）が2文以上になったら、`- **ラベル**:` の行だけにして本文を直下にネストした `-` 箇条書きへ分ける（1箇条1文。フローの要点+詳細と同じ考え方）。1文で済むものは `- **ラベル**: 本文` のまま1行でよい

  ```markdown
  - **事前条件**:
    - 事務所・ユーザーが存在すること
    - 添付ファイルがある場合は事前にアップロードが完了していること
  ```
- ID 記法の統一: 定義は表の ID 列（CMP / T）、文中参照は素の ID（CMP-01 / T-01）、ID⇔内容の対応（`コンポーネントID:` 行）はツール所有で render.js が同期する
- 曖昧語禁止: 「適切に / 必要に応じて / など / 等 / 柔軟に / できるだけ」を仕様に書かない。条件・範囲を具体化する（lint が検出）
- 表のセル内に `|` を書かない（表が壊れる）。縦棒が必要なら全角 `｜` を使う（例: `列挙(a｜b)`）。長文になるセルは手順の分割・`補足` への抽出で構造化する
- 定数が config・環境変数経由で実装される場合は根拠セルに `（drift-ok: <経路>）` を書く（drift 突合をスキップ。理由なしの drift-ok 禁止）
- bundled router（1ファイルで複数 UC のエンドポイントをまとめる設計）の場合、router を maps_to に含めず 公開インターフェース の パス または メソッド の値セルに `（drift-ok: bundled router）` を書く（endpoint-drift をスキップ）
- フローの各手順は2層で書く: `N. **要点**`（業務語の見出し1文・40文字以内。図のノードラベルになる。コード識別子を書かない）の行 + 直下の `-` 箇条書きで詳細（実装レベル。リポジトリ・メソッド名で書く。1箇条1文。`エラー:` / `契機:` / `遷移先:` / `終了条件:` の句も1箇条1つ）。短い手順は ` — ` 区切りで同一行に書いてもよい。太字省略時は本文の第一文（最初の「。」まで）が図に使われる
- 長いフロー（目安10手順超）は節目に `### 章名` を置く。render.js が章ごとの subgraph として描く
- 手順位置参照禁止（「手順 3〜4 を繰り返す」NG）。ループは `N. 繰り返し: <対象>。終了条件: <条件>` と書き、内容の手順を**ネストした番号リスト**にする（`-` はその手順自身の詳細で、内容の手順にならない）。ネスト1段まで。超えるなら設計書を分割
- tx 境界は `N. トランザクション: <理由>` と書き、内容の手順をネストした番号リストにする。文章で「同一トランザクション」と書かない
- `例外` は1原因1エントリ。フロー手順の文中に送出点を紐づける。バックエンドは `エラー: <発生条件> → <例外型>` で例外表の列は `例外型` / `発生条件` / `表示文言`（任意。例外型ごとに初出の1回だけ書く）。画面設計書は例外クラスが実在しないため `エラー: <発生条件> → <方式>` で紐づけ、例外表の列は `方式` / `発生条件` / `内容`（列順固定。`方式` が先頭）。`内容` は `方式` が `アラート表示` なら画面に出す文言（drift 突合の対象）、`画面遷移` なら遷移先の画面名（業務語のため drift 対象外）、`無言` なら空でよい（drift 対象外）
- `テスト仕様` の必須列: `ID`（T-XX）/ `レベル`（単体/結合/E2E）/ `テスト名`。任意列: `種別`（正常系/異常系/境界値）/ `前提条件` / `期待結果` / `備考`。列順は短い列を左、長文になる `テスト名`・`備考` を右端に置く: `ID / レベル / 種別 / テスト名 / 備考`。例外検証はいずれかのセルに `例外.<発生条件>` を書く（備考 推奨）。全 例外 に対応テスト必須。ID は `T-<2〜3桁>`（枝番英小文字1字可。例: T-44b）
- `テスト名` はテストコードのケース名と一致させる（drift が突合する）。文型は「〜の状態で／〜すると／〜になる」で前提・操作・期待を含め、利用者に見える振る舞いを主語にする。内部関数・変数名は判定基準として必要な場合のみ括弧で後置する（例:「編集で分岐した状態で送信すると、新しいメッセージが編集元の親にぶら下がる」）。前提・期待の詳述は 前提条件 / 期待結果 列へ
- `テスト名` に実装言語の識別子として使えない記号（`・`・`=`・`%`・数式記号等）を含めそうになったら、`drift-ok` で逃げずに**先に `テスト名` を記号なしの表現へ書き直す**（意味を保ったまま言い換える。例: 数式的な表現ではなく「〜の逆数」「〜の割合」のような自然文にする）。テストコードのケース名はその記号なし表現とそのまま一致させる。`drift-ok` は言い換えでは自然さを著しく損なう場合のみの最終手段（理由なし使用は禁止）
- 文は業務語で始め、実装識別子は括弧で後置する（`要点`・`説明`・`備考`・`内容` 共通）。設計書が使う専門用語（プロダクト固有の概念・略語）はユビキタス言語辞書に定義してから使う
- 1手順1責務: 手順の本文が長く折り返すなら、手順の分割か `エラー:`・`定数`・`補足` への抽出で構造化する
- `型` 語彙: `整数`/`数値`/`文字列`/`真偽`/`日時`/`パス`/`列挙(a｜b)`（表のセル内のため縦棒は全角）。ドメイン公開操作のみ `操作`。出力の型はこれに加えて `オブジェクト`/`配列`/`ストリーム` も使える（構造は 説明 に書く）。出力でも型は空にしない
- ドメイン: `入出力` に公開操作、`状態` に集約構造と不変条件
- バリデーション: 独立セクション禁止。`検証` 列の意味は 入力/出力 で異なる: 入力は制約違反時に例外を送出する条件（違反は `例外` + `エラー:` + テスト行の `例外.<発生条件>` で担保する）、出力は保証される値域・形式（例: 「usage_pct は 0〜100」「kind は 'web'/'rag' のいずれか」）。該当する制約がなければ空でよいが、列自体は残す（列を削らない）
- 画面のインタラクション: 手順の文中に `契機: <トリガー>` / `遷移先: <画面>` の句を書く。順序のない操作イベントも手順として列挙可
- 使用コンポーネント一覧表禁止。依存は `depends_on` が正本、本文は `CMP-{番号}` インライン参照のみ。CMP の正本は コンポーネント構成 の `コンポーネント`（ID / 名前の表）で、本文参照の実在（unknown-component-ref）と詳細設計の存在（uncovered-component）を lint が検証する。コンポーネント詳細設計の冒頭区画の `コンポーネントID:` 行は render.js が構成から自動付与・訂正する（ツール所有。手で書かなくてよい）
- 呼び出し元の名指し禁止: ドメイン・外部サービス・コンポーネントのように複数の設計書から再利用されうる設計書の 入出力 に「呼び出し元（UC-XX）」のような依存元の名前を書かない。依存は呼ぶ側（UC 等）の `depends_on` が正本で、逆方向（呼ばれる側）の本文に呼び出し元を固定すると将来の再利用時にズレる。物理的な行き先（`出力先: HTTPレスポンスヘッダー` 等）は依存関係ではないので書いてよい。呼ぶ側の本文で `詳細は {node_id} を参照` と `depends_on` 先を案内するのは正しい使い方（CMP-XX 参照と同じ方向）

### 横断関心事（00_共通）

- ログ・監視・認証・エラー変換・リトライの正本は `00_共通/` のポリシー（エラーポリシー / ログ・監視ポリシー / 認証・認可ポリシー）。UC 設計書には**逸脱・追加分のみ** `非機能` に理由つきで書き、`depends_on` に該当ポリシーを宣言する（ポリシー変更時の影響UCが impact.js で列挙できる）
- ミドルウェア相当（認証・テナント解決・request_id 採番・アクセスログ）は UC のフローに書かない。所有者検証のような業務ルールはフローに書く
- 共通化の基準: 3つ目のUCで同じ記述が出たら共通ポリシーか独立設計書へ昇格し `depends_on` で参照する。手順のコピペ禁止。検証（drift）か共通実装（maps_to）を伴わないポリシーは作らない
- 機械検証: 公開インターフェース の 認証 の値は 認証・認可ポリシーの `認証語彙`（箇条書き）と突合される（auth-vocab-drift）。ログ・監視の逸脱記述があるのに `depends_on` にログ監視ポリシーが未宣言だと警告される（undeclared-policy-dep）

### 公開インターフェース

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

```markdown
## 公開インターフェース

| 項目 | 値 |
|---|---|
| プロトコル | REST |
| メソッド | POST |
| パス | /api/orders |
| 認証 | 必須(一般ユーザー) |
| 成功 | 201 |

## 例外

| 例外型 | 発生条件 | 公開結果 | 表示文言 |
|---|---|---|---|
| DomainError | 在庫が不足 | 409 | 在庫が不足しています |
```

- プロトコルは REST / GraphQL / CLI / イベント。認証は 不要 / 必須(ロール)
- 失敗時の対応は `公開インターフェース` に書かない。`例外` 表の `公開結果` 列が正本（発生条件と公開結果が1エントリで揃うので参照整合性チェックが不要になる）。ステータスコードはエラーポリシーに従う（policy-drift が突合）
- 概要の `API仕様.md` はパス⇔UC の目次に留める。ステータス・認証 の正本は各 UC の `公開インターフェース`・`例外`

### 図（Mermaid）

- 詳細設計に図を**手で書かない・生成する**。`render.js` が フロー -> flowchart・sequenceDiagram / `状態` の遷移表 -> stateDiagram / 概要の `遷移`・`エンティティ` 表 -> 画面遷移・状態遷移図 を**各設計書の末尾マーカー区間に埋め込む**（hooks で常に最新。仕様を直せば図も追従する）。詳細設計のマーカー区間外の手書き mermaid は `manual-mermaid` が警告する
- フロー詳細の `クラス.メソッド` 呼び出し列から sequenceDiagram も自動生成する（参加者2つ以上のとき）。描くのは境界と順序のみ: Client の開始・応答矢印（公開インターフェースから）と `###` 章の全幅バンド。内部処理の手順は描かない（flowchart の担当）。コードが存在すれば参加者⇔実装ファイルの対応表も併記される（maps_to から class 定義を逆引き）
- 横断図は `.spec-runner/scan/dashboard.md`（健康表・警告一覧）。AI が phase-gate チェックに使う。`.gitignore` 対象
- 手書き Mermaid が許されるのは**構造化データを持たない俯瞰図**（システム俯瞰・システム構成・ドメイン概念・コンポーネント構成）のみ。画面遷移・状態遷移は `遷移` の表が正本（手で図を書くと二重正本になる）
- 手書き図のフェンスは必ず ```mermaid タグ付きで書く（タグなしは描画されず `untagged-mermaid` が警告）
- 手書き図のラベルに括弧・記号を入れるときは `A["テキスト（注）"]` のように必ず `"…"` で囲む（クォートなしの括弧は構文エラー。`mermaid-label-quote` が警告）

```markdown
## 状態

状態一覧: 下書き、確定、出荷済み

| 元 | 先 | 条件 |
|---|---|---|
| 下書き | 確定 | 確定操作が成功 |
```

### 例

```markdown
# UC-ページスクレイピング 詳細設計

## 概要

- **目的**: 事前起動した Chrome 上の縦書きビューアから全ページのスクリーンショットを取得する
- **トリガー**: CLI から手動実行
- **事前条件**: launch_chrome.sh で Chrome がデバッグポートつきで起動済みであること
- **事後条件**: 全ページのスクリーンショットが 出力 の命名規則で保存されている

## 入出力

### 入力

| 名前 | 型 | 既定値 | 検証 | 説明 |
|------|------|------|------|------|
| start_page | 整数 | 1 | | 再開時の開始ページ番号 |

### 出力

| 名前 | 型 | 既定値 | 検証 | 説明 |
|------|------|------|------|------|
| screenshots | パス | | | 出力先: data/screenshots/page_{page:03d}.png。各ページのスクリーンショット |

## 例外

| 例外型 | 発生条件 | 公開結果 | 表示文言 |
|--------|---------|---------|----------|
| ScraperError | CDP 接続に失敗 | | ブラウザに接続できません |
| ScraperError | スクリーンショット撮影・保存に失敗 | | |

## 定数

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

## 主要フロー

1. **ブラウザ接続**
   - CDP_URL の Chrome に CDP 接続する
   - エラー: 接続失敗 → ScraperError
2. **開始待ち** — 「準備ができたら Enter を押してください」と表示し入力を待つ
3. 繰り返し: ページごと（start_page から最大 MAX_PAGES 回）。終了条件: ArrowLeft 後の page.url が直前と同一なら最終ページとして正常終了
   1. 現在ページを撮影し 出力 の screenshots の書式で保存する。エラー: 撮影・保存失敗 → ScraperError
   2. ArrowLeft を送出し PAGE_WAIT_MS 待つ（縦書きのため次ページ方向は左）

## テスト一覧

| ID | レベル | 種別 | テスト名 | 備考 |
|----|--------|------|---------|------|
| T-01 | 結合 | 正常系 | 指定ページ数分のスクリーンショットが 出力 の命名規則で保存される | |
| T-02 | 結合 | 境界値 | ArrowLeft 後に URL が変化しない場合、最終ページと判断して正常終了する | |
| T-03 | 結合 | 正常系 | start_page 指定時、そのページ番号からファイルが始まる | |
| T-04 | 結合 | 異常系 | CDP 接続失敗時に ScraperError を送出する | 例外.CDP 接続に失敗 |
```

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

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

**lint（仕様内整合）**: 見出し構造の欠落（missing-structure）/ 必須ブロック欠落・順序違反・未知ブロック / 入出力 の小見出し欠落（missing-io-sections）/ 死に定数 / 値の直書き / 例外カバレッジ / T-XX 形式・重複 / 未参照 入力（dead-input）/ 入力・出力の型記入漏れ（missing-type）/ 曖昧語 / 要点40文字超（long-headline）/ ポリシー依存の未宣言（undeclared-policy-dep）/ 手書き mermaid（manual-mermaid）/ タグなし mermaid（untagged-mermaid）/ クォートなしラベル（mermaid-label-quote）/ HTTP method vs 成功ステータス整合（GET→200 / POST→200,201 等）/ 状態遷移の 元・先 が状態一覧に未定義 / depends_on に存在しない node_id / 複数ノードが同一ファイルを maps_to / 循環 depends_on / 業務ロジック概要の UC 一覧に対応する詳細設計が存在しない（uncovered-uc）/ 画面一覧に対応する詳細設計が存在しない（uncovered-screen）/ CMP-XX トレーサビリティ（uncovered-component・unknown-component-ref）/ maps_to 10件超（large-uc）

**drift（仕様⇔実装。maps_to 先コードを文字列突合）**: 定数（名前 or 値。根拠セルの `drift-ok:` でスキップ可）/ 公開インターフェース の パス・メソッド（Router 未配線検出。値セルの `drift-ok:` でスキップ可）/ 例外型 / 入力名 / T-XX 双方向 / T-XX の テスト名 完全一致（空白・`-`・`_` を除去して正規化。言い換え時はセルに `（drift-ok: <理由>）` を付ける）/ エラーポリシーとの例外型↔ステータスコード突合（policy-drift）/ 認証語彙との突合（auth-vocab-drift）

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

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

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

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

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

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

```bash
node .spec-runner/scripts/extract.js <node_id> --blocks 概要,公開インターフェース,入出力,例外,定数,フロー
```

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

## 文書品質

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

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

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

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