> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fim.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 貢献する

> FIM One貢献者向けの開発規約、型安全性、テスト、およびコード品質基準。

<Tip>
  このページは開発規約とコード品質基準をカバーしています。パイオニアプログラム、フィールドテスト、PRプロセス、およびコミュニティリンクを含む完全な貢献ガイドについては、[GitHubのCONTRIBUTING.md](https://github.com/fim-ai/fim-one/blob/master/CONTRIBUTING.md)を参照してください。
</Tip>

## セットアップ

前提条件: Python 3.11+、[uv](https://docs.astral.sh/uv/)、Node.js 18+、pnpm。

```bash theme={null}
git clone https://github.com/fim-ai/fim-one.git && cd fim-one
cp example.env .env                        # LLM_API_KEY is optional for contributors
uv sync --all-extras                       # Python dependencies
cd frontend && pnpm install && cd ..       # frontend dependencies
bash scripts/setup-hooks.sh                # pre-commit hooks (required)
```

<Note>
  `LLM_API_KEY` はバックエンドをローカルで実行するか、コミット時に自動翻訳されたロケール出力をプレビューするためにのみ必要です。キーを持たないコントリビューターは、EN の変更をコミットできます。GitHub Actions ワークフローが PR マージ後に `master` で翻訳します。下記の [i18n](#i18n) を参照してください。
</Note>

すべてが機能することを確認します:

```bash theme={null}
uv run pytest tests/ -x -q                # tests
uv run mypy src/fim_one/                   # type check
uv run ruff check src/                     # lint
cd frontend && pnpm build && cd ..         # frontend build
```

***

## 型安全性

mypy strict モードが強制されています。コードベース全体がゼロエラーで通過し、プリコミットフックは段階的な `.py` ファイルすべてに対して完全なインポートチェーン検査を実行して mypy を実行します。

**ルール:**

* すべてのパブリック関数に型ヒントが必須です。
* `# type: ignore` は `import-untyped`（スタブのないサードパーティライブラリ）を除いて使用しないでください。
* 前方参照には `from __future__ import annotations` を使用してください。
* 実際の型を修正してください -- CI を通すためにエラーを抑制しないでください。

## テスト

すべての新しいモジュールには、対応するテストファイルが**必須**です。すべての機能コミットにはテストを含める必要があります。

| 規約   | パターン                         |
| ---- | ---------------------------- |
| ファイル | `tests/test_{module}.py`     |
| クラス  | `Test{Feature}`              |
| メソッド | `test_{behavior_under_test}` |

**ルール:**

* コミット前にすべての既存テストが成功している必要があります: `uv run pytest tests/ -x -q`.
* テストは外部サービスに依存してはいけません -- `unittest.mock` / `AsyncMock` を使用してデータベース、MCP サーバー、HTTP エンドポイント、および LLM 呼び出しをモックしてください。
* カバレッジ付きでテストを実行してください: `uv run pytest --cov=fim_one`.

## コードスタイル

* **非同期ファースト。** I/O バウンド操作には `async def` を使用します。同期呼び出しは `asyncio.to_thread()` でラップして、イベントループをブロックしないようにします。
* **Ruff によるリンティング。** `uv run ruff check src/` -- 行の長さは 100 文字です。
* **最小限の `__init__.py` エクスポート。** パブリック API のみを再エクスポートし、内部シンボルはプライベートに保ちます。
* **パッケージマネージャー。** Python には `uv`、フロントエンドには `pnpm` を使用します。`pip` や `npm` は使用しないでください。

***

## Git規約

**アトミックコミット。** 1つの論理的な変更ごとに1つのコミット。関連のない変更は一緒に開発されていても分割してください。

**コミットメッセージ形式:** `type: description`

| Type       | 使用時期           |
| ---------- | -------------- |
| `feat`     | ユーザー向けの新機能     |
| `fix`      | バグ修正           |
| `refactor` | 動作変更のないコード再構成  |
| `docs`     | ドキュメントのみ       |
| `test`     | テストの追加または更新    |
| `chore`    | ビルド、CI、依存関係の更新 |

**`--no-verify`でフックをスキップしないでください。** pre-commitパイプラインは、エラーがリポジトリに到達する前に検出するために存在します。

***

## Pre-commit hook pipeline

フックはすべてのコミットで自動的に実行されます。各ステップに関連するステージング済みファイルのみを処理します。Pythonファイルのみを変更した場合、i18nステップはスキップされます（その逆も同様）。

| Order | Step               | Trigger                                                                                            | What it does                                                                       |
| ----- | ------------------ | -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| 0     | Locale-edit guard  | `messages/{locale}/`、`docs/{locale}/`、または `README.{locale}.md` の下にあるステージング済みファイル                   | コミットを中止します——オーバーライドはできません。代わりに `scripts/translation-glossary.md` を使用して翻訳を修正してください。 |
| 1     | OpenAPI spec regen | `src/fim_one/web/**/*.py` が変更された場合                                                                 | FastAPIルートから `docs/openapi.json` を再エクスポートします                                       |
| 2     | i18n translation   | `messages/en/*.json`、`docs/*.mdx`、または `README.md` が変更された場合（ローカル `LLM_API_KEY` が必要、ない場合はマージ後にCIが処理） | 新規/変更されたキーをすべてのターゲットロケールに翻訳します                                                     |
| 3     | mypy type checking | `src/fim_one/**/*.py` の任意のファイルが変更された場合                                                             | ステージング済みファイルの完全なインポートチェーンでmypyを実行します                                               |
| 4     | MDX validation     | `.mdx` ファイルがステージングされた場合                                                                            | Mintlifyに到達する前にJSX/MDX構文を検証します                                                     |

いずれかのステップが失敗した場合、コミットは中止されます。報告されたエラーを修正して再度実行してください。

## i18n

FIM One は6つのロケール（EN、ZH、JA、KO、DE、FR）をサポートしています。翻訳は完全に自動化されています。

**英語のソースファイルのみを編集してください：**

* `frontend/messages/en/{namespace}.json` -- UI文字列
* `docs/*.mdx`（ロケールサブディレクトリではなくルートレベル）-- ドキュメント
* `README.md` -- プロジェクトREADME

その他のロケールファイル（`messages/zh/`、`docs/zh/`、`README.zh.md`など）は**自動生成**され、プリコミットフックは手動編集されたファイルのコミットを無条件に拒否します。誤訳を修正するには、すべての翻訳ルールのシングルソースオブトゥルースである[`scripts/translation-glossary.md`](https://github.com/fim-ai/fim-one/blob/master/scripts/translation-glossary.md)を編集してから、`uv run scripts/translate.py --files <en-sources> --force`で影響を受けるファイルを再生成してください。すべての用語集の修正は5つのロケール全体に永続的に適用されます。

**ロケールファイルを生成する2つの方法：**

1. **ローカルプリコミットフック** -- `.env`で`LLM_API_KEY`が設定されている場合に実行されます。翻訳はプッシュ前に行われるため、出力をプレビューできます。
2. **CIフォールバック** -- ローカルフックにキーがなくスキップされた場合、[`.github/workflows/i18n-sync.yml`](https://github.com/fim-ai/fim-one/blob/master/.github/workflows/i18n-sync.yml)はマージ後に`master`で翻訳し、結果を自動コミットします。

APIキーを持たないコントリビューターは自由にEN変更をコミットできます——CIパスはロケールが正しく適用されることを保証します。

**新しいi18n名前空間を追加する：** `messages/en/{ns}.json`を作成してください。その他のロケールファイルは次のコミット時またはマージ後のCI上で生成されます。

**完全な再翻訳を強制する：** `uv run scripts/translate.py --all`（ローカル`LLM_API_KEY`が必要）。

## データベースマイグレーション

開発環境ではSQLite、本番環境ではPostgreSQLを使用します。1つのAlembicマイグレーションファイルセットが両方で動作する必要があります。

**主なルール：**

* 新しいORMモデルまたはカラムには**必ず**マイグレーションが必要です -- `metadata.create_all()`に依存しないでください。
* すべてのマイグレーションは**べき等**である必要があります -- `fim_one.migrations.helpers`のヘルパー（`table_exists`、`table_has_column`、`index_exists`）を使用してください。
* ブール値のデフォルト値：`server_default=sa.text("FALSE")` / `sa.text("TRUE")`。`"0"` / `"1"`は使用しないでください -- PostgreSQLはブール型カラムに対して整数リテラルを拒否します。
* SQLiteは`ALTER COLUMN`ができません -- カラム制約の変更には`op.batch_alter_table()`を使用してください。
* マイグレーションを作成した後、すぐに`uv run alembic upgrade head`を実行して適用してください。

## クイックリファレンス

```bash theme={null}
# Development
./start.sh dev                            # hot reload (Python + Next.js HMR)
./start.sh dev:api                        # API only, dev mode (hot reload)
./start.sh dev:ui                         # Frontend only, dev mode (HMR)
./start.sh api                            # FastAPI only (headless)

# Quality checks
uv run pytest tests/ -x -q               # tests (stop on first failure)
uv run pytest --cov=fim_one              # tests with coverage
uv run mypy src/fim_one/                  # type check
uv run ruff check src/                    # lint

# i18n
uv run scripts/translate.py --all         # force full retranslation

# Database
uv run alembic upgrade head               # apply migrations
uv run alembic revision -m "description"  # create new migration
```
