---
title: "Tanrei の作り方"
description: "2 つの信頼できる情報源、仕様起点のワークフロー、そして 5 つのプラットフォームとドキュメント、ステータス表の整合を保つドリフトチェック。"
url: "https://tanrei.chnotchy.com/ja/project/how-tanrei-is-built/"
last_updated: 2026-10-18T00:51:38.000Z
---

# Tanrei の作り方

> 2 つの信頼できる情報源、仕様起点のワークフロー、そして 5 つのプラットフォームとドキュメント、ステータス表の整合を保つドリフトチェック。

Tanrei は、1 つのリポジトリから 1 つのデザインシステムを 5 つのプラットフォームに届けています。これが成り立つのは、リポジトリそのものが間違いを起こしにくい構造になっている場合だけです。ある場所での変更は、全体に行き渡るか、さもなければはっきりと失敗しなければなりません。このページでは、それを実現する仕組みを説明します。

## 2 つの信頼できる情報源

判断が書かれているディレクトリは 2 つだけです。

| ディレクトリ | 内容 | 形式 |
| --- | --- | --- |
| `tokens/` | すべてのデザイン上の値 | Design Tokens Community Group 形式（2025.10） |
| `specs/` | すべてのコンポーネントの契約 | JSON（`specs/component.schema.json` で検証） |

それ以外はすべて派生物です。プラットフォームごとに生成されるトークンファイル、各プラットフォームの実装、このドキュメントの表、ステータス表がこれにあたります。派生物が情報源と食い違っていれば、定義上、間違っているのは派生物のほうです。

## 仕様に含まれるもの

コンポーネント仕様はプラットフォームに依存しません。記録されるのは、構成要素、プロパティ、スロット、イベント、状態、番号付きの要件として書かれた振る舞い、アクセシビリティの契約（ロール、キーボード操作表、ラベル付け）、結び付けるトークングループです。さらに、全プラットフォームが同じ ID でスナップショットを撮る基準描画である**フィクスチャ**と、中立的な名前を各プラットフォームの流儀に対応づける **platforms** ブロックを持ちます。

振る舞いは EARS 記法で書きます。文型が制約されているので、テストと突き合わせやすくなります。

```text
WHEN the user activates the button by pointer, touch, Enter or Space
THE button SHALL emit click exactly once.
```

各要件には `BTN-1` のような ID があり、どのプラットフォームのテストもこの ID を参照します。

## ワークフロー

1. **提案する。** 仕様を書く、または変更します。必要ならトークンも変更します。新しいコンポーネントと破壊的変更は、仕様を変える前にメンテナーが決めます。
2. **検証する。** `pnpm validate` がスキーマの検査、トークンの lint、すべてのテーマとコントラストレベルでのコントラスト不変条件の検証を行います。
3. **生成する。** `pnpm generate` がトークンの出力、ひな形、ステータス表を再生成します。
4. **実装する。** 仕様が挙げる各プラットフォームに、ユニットテスト、スナップショットテスト、アクセシビリティテストとともに実装します。
5. **確認する。** `pnpm check` がドリフトチェックを含むすべてを順に実行します。これが通らなければなりません。
6. **記録する。** changeset を追加します。パリティこそがプロダクトなので、全パッケージは同じバージョンで揃えて進めます。

プラットフォームの公開インターフェースを、同じコミットで仕様にも同じ変更を加えることなく変えることはできません。

## ドリフトはビルド失敗

- **再生成の差分。** CI はすべての派生ファイルを再生成し、コミット済みの内容と異なれば失敗します。生成ファイルを手で編集しても、生き残ることはありません。
- **パリティチェック。** 仕様が宣言する各プラットフォームについて、実装、テスト、フィクスチャごとのスナップショット、そしてそのコンポーネントの英語と日本語のドキュメントページが揃っていることを要求します。サイトのほかの言語にどのページが必要かは、ドキュメントサイトの別のチェックが確かめます。ステータス表も同じ事実から計算されるため、実在する以上のことは主張できません。
- **コントラスト不変条件。** コントラストを満たさないスキームは、そもそも出力されません。
- **スナップショットの規律。** スナップショットの差分は「発見」です。ベースラインを更新してよいのは、その見た目の変化が仕様またはトークンの変更の意図した結果である場合だけです。

## パリティの定義

パリティとは、**同じトークン**、**同等の見た目**、**同じ状態**、**同じアクセシビリティの意味**を持つことです。API が同一であることではありません。Compose は `enabled` を受け取り、Flutter は `onPressed` を null にしてボタンを無効化し、SwiftUI は `.disabled(_:)` を使います。こうした対応は仕様の platforms ブロックに書かれ、各コンポーネントのページに表示されます。

## エージェントにとって安全なワークフロー

人にも AI エージェントにも同じ規則が適用されます。そして可能な限り、信頼ではなくツールによって強制します。

- **階層化された規則。** ルートの短い `AGENTS.md` がプロジェクトの憲法を定め、入れ子のファイルがトークン、仕様、各パッケージのローカルな規則を加えます。入れ子の規則はルートの規則に追加できますが、弱めることはできません。
- **レーン。** プラットフォームの作業は、そのプラットフォームのパッケージ内に限定されます。SwiftUI を実装するエージェントが Compose に触れる理由はありません。
- **フック。** 生成ディレクトリへの編集、`--no-verify`、スナップショットのベースラインの更新はツールのレベルでブロックされ、セッション終了時にはドリフトチェックが走ります。
- **スキル。** コンポーネントやトークンの追加のような繰り返し行う手順は、ステップごとのスキルとして文書化され、毎回同じやり方で実行されます。
- **公開はしない。** レジストリへのリリースはメンテナーが決めることです。自動化された主体がそれを行うことはできません。

> [!NOTE]
> **ノート**
>
> このドキュメントも同じ規則に従っています。ステータス、トークンリファレンス、コンポーネントの仕様表は、ビルド時にリポジトリのデータから描画されます。手で書いているのは文章だけです。
