# 機能設計書 17-doom profile

## 概要

本ドキュメントは、Doom Emacsのプロファイル管理コマンド「doom profile」の機能設計を定義する。このコマンドは、複数のEmacs設定プロファイルを管理するための機能を提供する。

### 本機能の処理概要

doom profileは、Doom Emacsのプロファイル管理コマンド群のルートコマンドである。現時点では主にprofile syncサブコマンドが実装されており、プロファイルの同期とロードファイルの生成を行う。

**業務上の目的・背景**：Doom Emacsは複数のプロファイルをサポートしており、異なる設定セットを切り替えて使用できる。doom profileコマンドはこれらのプロファイルを管理し、プロファイルローダーを最新の状態に保つ。これにより、ユーザーは複数の設定（例：仕事用と個人用）を簡単に切り替えられる。

**機能の利用シーン**：
- 複数のプロファイルを使用している場合
- プロファイル設定を変更した後
- doom syncから自動的に呼び出される
- 新しいプロファイルを追加した後

**主要な処理内容**：
1. 既存プロファイルの読み込み（doom-profiles-read）
2. プロファイルの自動検出（doom-profiles-autodetect）
3. プロファイルの変更検出（追加、削除、変更）
4. プロファイルローダーの再生成（doom-profiles-write-load-file）

**関連システム・外部連携**：
- doom-profile-cache-file: プロファイルキャッシュ
- doom-profile-load-file: プロファイルローダー

**権限による制御**：特になし。

## 関連画面

本機能はCLIコマンドであり、GUIの画面は持たない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ターミナル | 主画面 | コマンドライン実行 |

## 機能種別

設定管理 / プロファイル管理

## 入力仕様

### 入力パラメータ

**doom profile** (親コマンド)
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | :partial tにより部分コマンド | - |

**doom profile sync**
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --all | フラグ | No | 全プロファイルを同期 | 現時点で必須 |
| --reload | フラグ | No | ロードファイルを強制再生成 | - |

### 入力データソース

- doom-profile-cache-file: 既存プロファイルのキャッシュ
- doom-profile-load-file: 現在のローダーファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| プロファイル変更 | メッセージ | 追加/削除/変更されたプロファイル |
| ローダー生成結果 | メッセージ | ローダーファイルのパス |

### 出力先

- doom-profile-cache-file: プロファイルキャッシュ
- doom-profile-load-file: プロファイルローダー

## 処理フロー

### 処理シーケンス

```
1. 既存プロファイル読み込み
   └─ doom-profiles-readでキャッシュから読み込み

2. プロファイル自動検出
   └─ doom-profiles-autodetectで利用可能なプロファイルを検出

3. ローダーファイルのバージョンチェック
   └─ doom-versionとの比較

4. 変更検出
   └─ 追加されたプロファイル（seq-difference）
   └─ 削除されたプロファイル（seq-difference）
   └─ 変更されたプロファイル（seq-intersection + 比較）

5. 変更がある場合
   └─ プロファイルキャッシュの更新（doom-file-write）
   └─ プロファイルローダーの再生成（doom-profiles-write-load-file）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{--all<br>指定?}
    B -->|No| C[エラー: 未実装]
    B -->|Yes| D[既存プロファイル読み込み]
    D --> E[プロファイル自動検出]
    E --> F{ローダー<br>存在?}
    F -->|No| G[再生成フラグON]
    F -->|Yes| H{バージョン<br>一致?}
    G --> I[変更検出]
    H -->|No| G
    H -->|Yes| I
    I --> J{変更<br>あり?}
    J -->|No| K[スキップ]
    J -->|Yes| L[変更表示]
    K --> M[終了]
    L --> N[キャッシュ更新]
    N --> O[ローダー生成]
    O --> P[成功メッセージ]
    P --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | バージョン整合性 | doom-versionとローダーのバージョンが一致しない場合は再生成 | profile sync時 |
| BR-02 | 変更検出 | プロファイルの追加/削除/変更を検出して報告 | profile sync時 |
| BR-03 | 個別同期未実装 | --allなしの個別プロファイル同期は未実装 | 常時 |

### 計算ロジック

**変更検出ロジック**:
```elisp
(let* ((pred    (lambda (a b) (eq (car a) (car b))))
       (added   (seq-difference new-profiles old-profiles pred))
       (removed (seq-difference old-profiles new-profiles pred))
       (changed (cl-loop for profile in (seq-intersection new-profiles old-profiles pred)
                         unless (equal (cdr profile)
                                       (alist-get (car profile) old-profiles))
                         collect profile)))
  ...)
```

## データベース操作仕様

本機能はデータベースを使用しない。ファイルベースでプロファイル情報を管理。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ユーザーエラー | --allなしで実行 | --allを指定して再実行 |

### リトライ仕様

特になし。

## トランザクション仕様

キャッシュファイルとローダーファイルは順次更新される。

## パフォーマンス要件

- ベンチマーク有効（:benchmark t）
- プロファイル数に応じた処理時間

## セキュリティ考慮事項

- プロファイルキャッシュは#o600のパーミッションで保存

## 備考

- 多くのサブコマンド（hash, new, archive, remove, rename, nuke）はスタブとして定義されており、未実装
- doom syncから自動的に呼び出される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: 親コマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | profile.el | `lisp/cli/profile.el` | 11-13行目の親コマンド定義 |

**読解のコツ**: `:partial t`は部分コマンドを示し、サブコマンドを持つことを意味する。

#### Step 2: syncサブコマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | profile.el | `lisp/cli/profile.el` | 15-56行目のsyncコマンド |

**主要処理フロー**:
- **15-17行目**: コマンド定義と引数
- **20-21行目**: --allなしの場合のエラー
- **22-26行目**: 既存・新規プロファイルの取得とバージョンチェック
- **27-35行目**: ローダー存在確認とバージョン不一致検出
- **38-55行目**: 変更検出と出力

#### Step 3: スタブコマンドを確認する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | profile.el | `lisp/cli/profile.el` | 58-68行目のスタブ定義 |

**読解のコツ**: `defcli-stub!`は未実装のコマンドを定義するマクロ。将来の拡張ポイントを示す。

### プログラム呼び出し階層図

```
doom profile (defcli! :partial)
    │
    └─ doom profile sync (defcli!)
           │
           ├─ doom-profiles-read
           │      └─ doom-profile-cache-file
           │
           ├─ doom-profiles-autodetect
           │
           ├─ doom-file-read
           │      └─ doom-profile-load-file
           │
           ├─ doom-profiles-outdated-p
           │
           ├─ seq-difference (追加/削除検出)
           │
           ├─ seq-intersection (変更検出)
           │
           ├─ doom-file-write
           │      └─ doom-profile-cache-file
           │
           └─ doom-profiles-write-load-file
                  └─ doom-profile-load-file
```

### データフロー図

```
[入力]                        [処理]                       [出力]

doom-profile-cache-file ───▶  プロファイル  ───▶  old-profiles
                               読み込み

ファイルシステム        ───▶  自動検出     ───▶  new-profiles

old-profiles            ───▶  差分計算     ───▶  added/removed/changed
new-profiles

変更リスト              ───▶  キャッシュ   ───▶  doom-profile-cache-file
                               更新

new-profiles            ───▶  ローダー生成 ───▶  doom-profile-load-file
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| profile.el | `lisp/cli/profile.el` | ソース | profileコマンドの主実装 |
| profiles.el | `lisp/lib/profiles.el` | ソース | プロファイル管理ライブラリ |
| doom-cli.el | `lisp/doom-cli.el` | ソース | CLIフレームワーク |
| sync.el | `lisp/cli/sync.el` | ソース | doom syncからの呼び出し |
