# Test Perspective

> Create, update, or deprecate Test Perspective Library (TPL) records in docs/test-perspectives/. Trigger when the user says: "テスト観点", "観点ライブラリ", "TPL", "観点を追加", "TPLを起こす", "TPLをdeprecate", "test perspective", "add TPL", "deprecate TPL", or similar phrases requesting test-perspective record maintenance.

- Skill: `kompiro/test-perspective` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add kompiro/test-perspective`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kompiro/test-perspective/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: kompiro (https://skillmd.com/u/kompiro)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kompiro/test-perspective

---


# Test Perspective (TPL) Skill

再発しうる失敗パターンを、構造化された「観点」として `docs/test-perspectives/` に蓄積・更新・deprecate する。
1 観点 = 1 ファイル。DesignDoc 作成時・新機能実装時・bug 修正時に該当 `topic` / `scope.packages` の観点が参照される状態を作るのが目的。

## 前提条件

このスキルはホスト repo が **`docs/test-perspectives/`（TPL）を採用している場合のみ** 意味を持つ。

- ディレクトリが存在しない場合は、まず「`docs/test-perspectives/` を新設して運用を始めるか」をユーザーに確認する。始める場合は最初の 1 件をこのスキルで作成し、必要なら `docs/test-perspectives/README.md`（運用方針の入り口）と `TEMPLATE.md`（この skill ディレクトリの [`TEMPLATE.md`](TEMPLATE.md) をコピーする）も用意する
- ディレクトリはあるが空 / `README.md` も `TEMPLATE.md` も無い、という状態でも動作する（既存ファイルが無ければスキャンは no-op）

## ホスト repo に依存する慣習

- **`topic` の controlled vocabulary**: ホスト repo が ADR の語彙を持つ場合（例: `docs/adr/README.md` のセクション見出し、`adr.config.json` の `topics` 等）はそれを使い、TPL と ADR で語彙を共有する。持たない場合は free-form の小文字 kebab トピックでよい
- **ファイル名規約**: 既定は `docs/test-perspectives/TPL-<番号>-<slug>.md`（見出し `TPL-<番号>`、ゼロ埋めなし、GitHub 番号ベース。詳細は下記「ファイルを作成する」）。ホスト repo が独自の規約（例: 日付ベースの `TPL-YYYYMMDD-NN-<slug>.md`）を持つ場合はそちらを優先する（ADR/AT の命名と同じ「host 独自規約優先」のエスケープ）
- **検証ツール**: ホスト repo が `tpl:validate`（frontmatter と一覧表の machine check）等を提供していれば、作成・更新後にそれを実行する。無ければ手動で frontmatter を確認する
- **関連 TPL クエリ**: ホスト repo が `tpl:related <topic>` 等を提供していればそれで関連 TPL を一覧する。無ければ `docs/test-perspectives/` 配下の frontmatter（`topic` / `scope.packages` / `applicable_to` / `known_consumers`）を grep する
- **定期 deprecation レビュー**: cadence（週次 / 月次 / 半期）と自動化（CI で review Issue を自動生成する等）はホスト repo に委ねる。このスキルは「`active` な TPL を放置しないため定期レビューを推奨」とだけ示す

## 手順

### 1. モードの判定

スキル起動時の引数・会話の文脈から、以下のどれかを判定する:

- **新規作成** — bug / test-infra Issue から、または原則（concepts / ADR）から、新しい観点を起こす
- **既存更新** — 新しい Issue が既存 TPL のパターンに該当する／チェックリスト・対処パターン・関連テストの refresh が必要
- **deprecate** — 構造変更などで、ある観点が原理的に発生しなくなった

### 2. 新規作成

#### 2-1. 起源を判定する

TPL は 2 つの起源から生まれる。frontmatter の `discovered_from` で区別できるようにする:

- **Retrospective（事後）** — `bug` または `test-infra` ラベルの Issue から、実際に起きた失敗を一般化する。`discovered_from.issue: "#N"` を持つ。`test-infra` は E2E flake / fixture / harness の問題で、典型的には testing 系トピックの観点を生む
- **Proactive（事前）** — アーキテクチャ原則 / 非目標 / north-star（`docs/concepts*` のようなファイルや ADR）から、原則が破られたときに起きるであろう失敗を予測して観点化する。`discovered_from.root_cause_file: "docs/concepts.*"` または `discovered_from.root_cause_adr: "ADR-..."` を持つ

起源が違うだけで、frontmatter スキーマ・3-Yes ルール・更新/deprecate の運用ルールはすべて同じ。

#### 2-2. 3-Yes ルールで作成可否を判断する

以下の 3 つすべてが Yes なら新規 TPL として起こす。1 つでも No なら、個別 Issue として処理して TPL は作らない:

1. 同じ root cause が **別の機能でも発生しうる** か?
2. 構造的なパターンとして **再発する可能性がある** か?
3. 既存の TPL でカバーされていない観点か?（既存 TPL のパターンに該当するなら「既存更新」へ）

#### 2-3. ファイルを作成する

- ファイル名: `docs/test-perspectives/TPL-<番号>-<slug>.md`（見出し `TPL-<番号>`、ゼロ埋めなし、`<slug>` は観点を端的に表す小文字 kebab）。**番号は GitHub の番号ベース**、優先順位は ADR-8 / ADR-10 と同じ:
  1. 紐付く Issue 番号 — retrospective TPL は起点の `bug` / `test-infra` Issue 番号（`discovered_from.issue` と揃う）
  2. Issue が無ければ PR 番号 — proactive TPL は原則 / ADR 起源で Issue が無いことが多いので、それを起こした DesignDoc PR の番号を使う（draft PR を先に開く運用と整合）
  3. どちらも無いときだけローカル採番（`docs/test-perspectives/` 内の既存最大 + 1）。
     ローカル採番だけは並行ブランチ間で衝突しうる — ホストが `@kompiro/tpl-tools`
     （>= 0.0.7）の `tpl validate` を持つ場合、重複 id は `duplicate-id` としてマージ時に
     検出されるので、採番後に必ず実行する

  番号は 1 TPL = 1 番号で一意にする。同じ Issue / PR から複数 TPL を切る場合は、番号を
  その起点を最もよく表す 1 本に与え、残りは次の優先順位へ進める（Issue → PR → ローカル採番。
  `start-dev` の「同じ Issue から 2 本目の ADR」と同じ運用）。同じ番号を `<slug>` 違いで
  共有すると `duplicate-id` 検査に落ちる。採番後はリネームしない（外部参照が番号を指すため）。
  ホスト repo が独自規約を持つ場合はそちらに従う。
- frontmatter と本文（5 節構成）の雛形は、この skill ディレクトリの [`TEMPLATE.md`](TEMPLATE.md) を使う。`TEMPLATE.md` をコピーして冒頭の HTML コメントを削除し、frontmatter と各節を埋める。本文は 観点 / 想定される失敗モード / チェックリスト（3〜5 項目）/ 既知の対処パターン / 関連テスト の 5 節。
  - `applicable_to` — 適用される **抽象パターン**。consumer の具体名は書かない（そちらは `known_consumers`）。consumer 空間が広すぎて列挙が無意味なら `known_consumers` ごと省略してよい
  - `known_consumers` — 新たに該当 consumer が見つかったら追記する
- ホスト repo が TPL の一覧表（`docs/test-perspectives/README.md` 等）を持つ場合はそこに行を追加する。`tpl:validate` 等があれば実行して frontmatter と一覧表の整合を確認する

> proactive を引用した DesignDoc は、その実装 PR で該当チェックリスト項目の contract test と AT AC を着地させる（"forward 運用"）。`acceptance-test` スキルがこの転記を行う。

### 3. 既存更新

新しい Issue が既存 TPL のパターンに該当する場合（3-Yes の 3 番目が No）、その TPL を更新する:

- `discovered_from` セクションに Issue を追記する
- チェックリスト・「既知の対処パターン」・「関連テスト」の更新が必要ならそれも行う
- 起源は変えない（retrospective の TPL に proactive の根拠が後付けされることはあるが、`discovered_from` に両方並べればよい）

### 4. deprecate

実装の構造変更などで、ある観点が **原理的に発生しなくなった** 場合:

- `status` を `deprecated` に変更する
- エントリ自体は **削除しない**。本文の末尾に「なぜ deprecated にしたか」の rationale を追記する（後から「この観点はなぜ消えたのか」を辿れるようにするため）。rationale には `deprecated` の語を含める（ホスト repo の validator がこれを要求することがある）
- より新しい TPL がこの観点を包含する場合は、その TPL を `superseded by TPL-<番号>` として rationale に明記する（ADR の `superseded_by` 運用と同じ）
- deprecate の **トリガー** は定期 deprecation レビュー（前述、cadence はホスト repo 次第）で起こすのが基本。レビューでは各 `active` TPL について「引用された `root_cause_file` / `root_cause_adr` は今も存在するか」「アーキテクチャの前提が変わっていないか」「これを包含するより新しい TPL があるか」を確認し、`keep` / `update` / `deprecate` を判断する

### 5. レビュー依頼

作成・更新・deprecate した TPL ファイル（と一覧表の差分）をユーザーに提示し、レビューを依頼する。

## TPL のライフサイクル

```
concept（docs/concepts.* / ADR）
   │   原則を実装に落とすときに違反しうる観点を抽出
   ▼
proactive TPL   ← 開発前に書く（予防可能な学習）
   │
   ▼
development（DesignDoc + 実装）
   │
   ▼
bug（proactive TPL でカバーできなかった失敗）
   │   実際に起きた失敗を一般化
   ▼
retrospective TPL   ← bug 修正と同じ PR で書く（不可避な学習）
```

- **proactive TPL** は **予防可能** な学習 — 書ければ bug を未然に防げる。書ければ書けるほど retrospective に学ぶしかない bug が減る
- **retrospective TPL** は **不可避** な学習 — 起きてからしか書けないが、起きたら必ず書く（同じ bug を 2 回起こさない）
- retrospective TPL を書くたびに「この観点を proactive TPL として書いておけたか?」を自問する。書けたはずなら、それは「proactive スキャンの漏れ」自体が次回のレトロスペクティブの素材になる（TPL としては記録しない）

## ADR との違い

- **ADR**: 過去の判断の記録（「我々はこう決めた」）
- **TPL**: 未来の検証の集約（「これを検証すべき」）

両者は frontmatter の `topic` / `scope.packages` を共有しているので、同じトピックで横串検索すれば「過去の判断」と「検証すべき観点」を同時に発見できる。

## 参照タイミング（他スキルとの連携）

- **DesignDoc 作成時**（`design-doc` スキル）: 該当 `topic` / `scope.packages` の既存 TPL を一覧し、さらに同じ topic の `concepts*` / 関連 ADR を読んで、まだ TPL になっていない原則で今回の設計が違反しうるものがないか確認する。あれば 3-Yes ルールに照らして proactive TPL を **同じ PR で** 起こす（このスキルを呼ぶ）
- **新機能の実装時 / 受け入れテスト作成時**（`acceptance-test` スキル）: AC を書く前に該当 TPL のチェックリストを確認し、引用した proactive TPL のチェックリスト項目を AC に転記する
- **bug 修正時**: 同じパターンの TPL がすでに存在しないか確認し、あれば `discovered_from` に追記する。なければ 3-Yes ルールで retrospective TPL の新規作成を検討する。併せて「この bug は proactive TPL を書いていれば防げたか?」も自問する

## スコープ外

`topic` / `package` に紐付かない **メタ観点**（全機能 PR に共通して適用する横断フィルタなど）は TPL スキーマに載せない。横串検索の単位（`topic` / `scope.packages`）を持たないものは TPL として管理する利点が薄いため。そういう観点はホスト repo の Issue / PR テンプレートのチェックリスト等で surface する。

