Skip to content

Commit e7068a7

Browse files
web-flowclaude
andcommitted
refactor: Config層独立化 + コード品質改善 + テスト拡充
## Config層の独立化 (Clean Architecture) - config/types.py: Config専用TypedDict定義 - config/exceptions.py: ConfigError例外クラス - config/constants.py: LEVEL_CONFIG定数(SSoT) - config/error_messages.py: シンプルなエラーメッセージ関数 - config/validation.py: collect_type_error関数 - 8つの既存configファイルからdomain importを削除 ## コード品質改善 - domain/validators/type_validators.py: 型検証のSingle Source of Truth - infrastructure/error_handling.py: 統一エラー処理ユーティリティ - application/validators.py: 新type_validatorsに委譲 - mypy型エラー修正 (domain/exceptions.py, config/threshold_provider.py) ## テスト拡充 (+85テスト) - test_cli.py: Config CLI テスト (10) - test_protocols.py: Protocol テスト (12) - test_version.py: バージョン テスト (10) - test_type_validators.py: 型検証 テスト (35) - test_error_handling.py: エラー処理 テスト (17) - test_threshold_equals_one修正: 閾値=1環境を作成するように変更 ## 結果 - pytest: 1460 passed, 3 skipped (Windowsでの権限テストのみ) - mypy: エラーなし - ruff: 修正済み 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent eae541c commit e7068a7

45 files changed

Lines changed: 3086 additions & 196 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

EpisodicRAG/CONTRIBUTING.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,47 @@ python -c "from domain import __version__; print(__version__)"
428428

429429
---
430430

431+
## Documentation Sync Process
432+
433+
### Bilingual Documentation Policy
434+
435+
EpisodicRAGプラグインは日本語を主言語とし、主要ドキュメントの英語版を提供しています。
436+
437+
1. **Primary Language**: Japanese (日本語)
438+
2. **Secondary Language**: English
439+
440+
> **翻訳方針**: 主要ドキュメント(README, QUICKSTART, CHEATSHEET)のみ英語版を維持します。その他のドキュメントは日本語のみとし、翻訳の維持コストを抑えます。
441+
442+
### Currently Synced Files
443+
444+
| Japanese | English | Status |
445+
|----------|---------|--------|
446+
| `README.md` | `README.en.md` | ✅ Synced |
447+
| `docs/user/QUICKSTART.md` | `docs/user/QUICKSTART.en.md` | ✅ Synced |
448+
| `docs/user/CHEATSHEET.md` | `docs/user/CHEATSHEET.en.md` | ✅ Synced |
449+
450+
### Sync Workflow
451+
452+
日本語ドキュメントを更新した場合、対応する英語ドキュメントも同期してください。
453+
454+
1. **Edit Japanese version first** - 日本語版を先に編集
455+
2. **Update English version** - 同じPR内で英語版を更新
456+
3. **Add sync header** - 英語ファイルの先頭にヘッダーを追加:
457+
```markdown
458+
<!-- Last synced: YYYY-MM-DD -->
459+
```
460+
461+
### Adding New Translations
462+
463+
新しい英語翻訳を追加する場合:
464+
465+
1. Copy structure from Japanese version(日本語版の構造をコピー)
466+
2. Translate content maintaining formatting(フォーマットを維持して翻訳)
467+
3. Add sync header with date(同期ヘッダーを追加)
468+
4. Update this table(上のテーブルを更新)
469+
470+
---
471+
431472
## サポート
432473

433474
質問や問題がある場合は、GitHub Issuesで報告してください。

EpisodicRAG/README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -227,22 +227,32 @@ L00001追加 → `/digest`せず → L00002追加
227227

228228
### 記憶定着サイクル
229229

230-
```text
231-
Loop追加 → `/digest` → Loop追加 → `/digest` → ...
232-
↑ 記憶定着 ↑ ↑ 記憶定着
230+
EpisodicRAGの最も重要な原則は、**Loopを追加したら都度 `/digest` を実行する**ことです。
231+
232+
```mermaid
233+
flowchart LR
234+
A[Loop追加] --> B["/digest"]
235+
B --> C[記憶定着]
236+
C --> A
237+
238+
style B fill:#90EE90,stroke:#228B22
239+
style C fill:#87CEEB,stroke:#4169E1
233240
```
234241

235-
この原則を守ることで、AIは全てのLoopを記憶できます。
242+
**やるべきこと:**
243+
```text
244+
L00001追加 → /digest → L00002追加 → /digest → ...
245+
```
236246

237247
**やってはいけないこと:**
238-
239248
```text
240-
L00001追加 → `/digest`せず → L00002追加
241-
242-
この時点でAIはL00001の内容を覚えていない
243-
(記憶がまだら=虫食い状態)
249+
L00001追加 → L00002追加 → /digest
250+
251+
この時点でL00001の内容をAIは覚えていない(まだらボケ)
244252
```
245253

254+
この原則を守ることで、AIは全てのLoopを記憶できます。
255+
246256
### Threshold(閾値)
247257
**定義**: 各階層のDigest生成に必要な最小ファイル数
248258

EpisodicRAG/docs/dev/API_REFERENCE.md

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
EpisodicRAGプラグインの**Python API仕様書**です。
66

7+
> **設計方針**: このドキュメントはSSoT原則に従い、リンク集として機能します。詳細な定義は各 `api/*.md` を参照してください。
8+
79
> **対応バージョン**: EpisodicRAG Plugin([version.py](../../scripts/domain/version.py) 参照)/ ファイルフォーマット 1.0
810
911
> 📖 用語・共通概念: [用語集](../../README.md)
@@ -48,45 +50,11 @@ Clean Architecture(4層構造)に基づいて、APIドキュメントを層
4850

4951
### 推奨インポートパス
5052

51-
```python
52-
# Domain層(定数・型・例外)
53-
from domain import LEVEL_CONFIG, __version__, ValidationError
54-
from domain.file_naming import extract_file_number, format_digest_number
55-
from domain.level_registry import get_level_registry
56-
57-
# Infrastructure層(外部I/O)
58-
from infrastructure import load_json, save_json, log_info, log_error
59-
from infrastructure.file_scanner import scan_files
60-
from infrastructure.user_interaction import get_default_confirm_callback
61-
62-
# Application層(ビジネスロジック)
63-
from application.shadow import ShadowTemplate, ShadowUpdater, CascadeProcessor
64-
from application.grand import GrandDigestManager, ShadowGrandDigestManager
65-
from application.finalize import RegularDigestBuilder, DigestPersistence
66-
from application.validators import validate_dict, is_valid_list
67-
68-
# Interfaces層(エントリーポイント)
69-
from interfaces import DigestFinalizerFromShadow, ProvisionalDigestSaver
70-
from interfaces.interface_helpers import sanitize_filename, get_next_digest_number
71-
from interfaces.provisional import InputLoader, DigestMerger
72-
73-
# 設定(configパッケージ)
74-
from config import DigestConfig
75-
```
53+
> 📖 完全なインポートパスは [ARCHITECTURE.md#推奨インポートパス](ARCHITECTURE.md#推奨インポートパス) を参照
7654
7755
### 依存関係ルール
7856

79-
```text
80-
domain/ ← 何にも依存しない(純粋なビジネスロジック)
81-
82-
infrastructure/ ← domain/ のみ
83-
84-
application/ ← domain/ + infrastructure/
85-
86-
interfaces/ ← application/
87-
```
88-
89-
> 📖 **アーキテクチャ詳細**: [ARCHITECTURE.md](ARCHITECTURE.md#clean-architecture)
57+
> 📖 詳細は [ARCHITECTURE.md#依存関係ルール](ARCHITECTURE.md#依存関係ルール) を参照
9058
9159
---
9260

EpisodicRAG/docs/user/FAQ.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ EpisodicRAGプラグインに関するよくある質問と回答集です。
2020
- [一般的な質問](#一般的な質問)
2121
- [導入・セットアップ](#導入セットアップ)
2222
- [日常的な使い方](#日常的な使い方)
23+
- [パフォーマンスと最適化](#パフォーマンスと最適化)
24+
- [バックアップと復旧](#バックアップと復旧)
25+
- [マルチユーザー・同時アクセス](#マルチユーザー同時アクセス)
26+
- [他ツールとの連携](#他ツールとの連携)
2327
- [トラブルシューティング](#トラブルシューティング)
2428
- [開発者向け](#開発者向け)
2529
- [関連ドキュメント](#関連ドキュメント)
@@ -114,6 +118,105 @@ flowchart TB
114118
115119
---
116120

121+
## パフォーマンスと最適化
122+
123+
### Q: 100件以上のLoopファイルがある場合、パフォーマンスに影響はありますか?
124+
125+
**A**: EpisodicRAGは大量のファイルを効率的に処理するよう設計されています。
126+
127+
- ファイルスキャンは増分検出(`last_digest_times.json`)で最適化
128+
- 1000ファイルでも5秒以内で検出完了
129+
- メモリ使用量は500ダイジェストで1MB未満
130+
131+
### Q: ストレージ要件はどのくらいですか?
132+
133+
**A**: 目安として:
134+
135+
| ファイル種類 | サイズ目安 |
136+
|------------|----------|
137+
| Loopファイル | 1-10KB/件 |
138+
| Weeklyダイジェスト | 5-20KB/件 |
139+
| ShadowGrandDigest | 50-200KB |
140+
| GrandDigest | 100-500KB |
141+
142+
****: 100 Loops + 20 Weeklies ≈ 2-3MB
143+
144+
---
145+
146+
## バックアップと復旧
147+
148+
### Q: バックアップはどのように取るべきですか?
149+
150+
**A**: 以下のディレクトリをバックアップしてください(優先順):
151+
152+
1. `Loops/` - 元データ(**最重要**
153+
2. `Essences/` - GrandDigest, ShadowGrandDigest
154+
3. `.claude-plugin/config.json` - 設定
155+
4. `.claude-plugin/last_digest_times.json` - 状態追跡
156+
157+
> 💡 Loops/さえあれば他は再構築可能です。
158+
159+
### Q: ShadowGrandDigestが破損した場合の復旧方法は?
160+
161+
**A**:
162+
1. `ShadowGrandDigest.txt`を削除
163+
2. `/digest` を実行して再構築
164+
165+
> 📖 詳細: [TROUBLESHOOTING.md](TROUBLESHOOTING.md#shadowgranddigest更新されない)
166+
167+
### Q: 誤ってファイルを削除してしまいました
168+
169+
**A**: 復旧手順は削除したファイルによって異なります:
170+
171+
| 削除ファイル | 復旧方法 |
172+
|------------|---------|
173+
| Loopファイル | Gitバックアップから復元、または手動で再作成 |
174+
| ShadowGrandDigest | `/digest`を実行して再生成 |
175+
| GrandDigest | `/digest weekly`を実行して再生成 |
176+
| config.json | `@digest-setup`を実行して再作成 |
177+
178+
---
179+
180+
## マルチユーザー・同時アクセス
181+
182+
### Q: 複数人で同じリポジトリを使えますか?
183+
184+
**A**: 現在の設計は**単一ユーザー**を想定しています。
185+
186+
- **読み取り**: 問題なし(複数人で同時閲覧可能)
187+
- **書き込み**: 競合の可能性あり(同時に`/digest`を実行すると不整合が発生する可能性)
188+
189+
> 💡 チーム利用の場合は、各メンバーが独自のプラグインインスタンスを持つことを推奨します。
190+
191+
### Q: 同時に複数のターミナルから操作できますか?
192+
193+
**A**: 推奨しません。
194+
195+
- `/digest`実行中に別ターミナルで`/digest`を実行するとファイル競合が発生する可能性があります
196+
- 1つのターミナルで操作を完了してから次の操作を開始してください
197+
198+
---
199+
200+
## 他ツールとの連携
201+
202+
### Q: 他のClaude Codeプラグインと併用できますか?
203+
204+
**A**: はい。EpisodicRAGは独立して動作します。
205+
206+
- 設定ディレクトリは`.claude-plugin/`で分離
207+
- 他プラグインとの干渉なし
208+
- コマンド名が重複しない限り問題なく併用可能
209+
210+
### Q: GitHubとの連携は可能ですか?
211+
212+
**A**: はい。[ADVANCED.md](ADVANCED.md)でGitHub連携の設定方法を説明しています。
213+
214+
- Loops/Essencesディレクトリをリポジトリに含める
215+
- `.gitignore`でキャッシュファイルを除外
216+
- 複数デバイス間での記憶共有が可能
217+
218+
---
219+
117220
## トラブルシューティング
118221

119222
問題が発生した場合は [TROUBLESHOOTING.md](TROUBLESHOOTING.md) を参照してください。

EpisodicRAG/docs/user/GUIDE.md

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,7 @@
1818

1919
### 記憶定着サイクル
2020

21-
EpisodicRAGの最も重要な原則は、**Loopを追加したら都度 `/digest` を実行する**ことです。
22-
23-
```mermaid
24-
flowchart LR
25-
A[Loop追加] --> B["/digest"]
26-
B --> C[記憶定着]
27-
C --> A
28-
29-
style B fill:#90EE90,stroke:#228B22
30-
style C fill:#87CEEB,stroke:#4169E1
31-
```
32-
33-
**やるべきこと:**
34-
```text
35-
L00001追加 → /digest → L00002追加 → /digest → ...
36-
```
37-
38-
**やってはいけないこと:**
39-
```text
40-
L00001追加 → L00002追加 → /digest
41-
42-
この時点でL00001の内容をAIは覚えていない(まだらボケ)
43-
```
44-
45-
> 📖 まだらボケの詳細は [用語集](../../README.md#まだらボケ) を参照
21+
> 📖 記憶定着サイクルの詳細は [用語集](../../README.md#記憶定着サイクル) を参照
4622
4723
---
4824

EpisodicRAG/scripts/application/validators.py

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,50 +13,15 @@
1313
files = validate_list(source_files, "source_files")
1414
"""
1515

16-
from typing import Any, Callable, Dict, List, Optional, Type, TypeVar
16+
from typing import Any, Dict, List, Optional
1717

1818
from domain.error_formatter import get_error_formatter
1919
from domain.exceptions import ValidationError
2020
from domain.validation import validate_type as _validate_type
21-
22-
# =============================================================================
23-
# 汎用ヘルパー関数(内部使用)
24-
# =============================================================================
25-
26-
T = TypeVar('T')
27-
28-
# _validate_type は domain.validation から再エクスポート(後方互換性維持)
29-
30-
31-
def _is_valid_type(data: Any, expected_type: Type[T]) -> bool:
32-
"""
33-
汎用型チェックヘルパー(例外を投げない)
34-
35-
Args:
36-
data: 検証対象のデータ
37-
expected_type: 期待する型
38-
39-
Returns:
40-
dataが期待する型ならTrue
41-
"""
42-
return isinstance(data, expected_type)
43-
44-
45-
def _get_or_default(data: Any, expected_type: Type[T], default_factory: Callable[[], T]) -> T:
46-
"""
47-
汎用デフォルト取得ヘルパー
48-
49-
Args:
50-
data: 検証対象のデータ
51-
expected_type: 期待する型
52-
default_factory: デフォルト値を生成する関数
53-
54-
Returns:
55-
dataが期待する型ならdata、そうでなければdefault_factory()の結果
56-
"""
57-
if isinstance(data, expected_type):
58-
return data
59-
return default_factory()
21+
from domain.validators import (
22+
get_or_default as _get_or_default,
23+
is_valid_type as _is_valid_type,
24+
)
6025

6126

6227
# =============================================================================

EpisodicRAG/scripts/config/__init__.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@
3737
from pathlib import Path
3838
from typing import List, Literal, Optional
3939

40-
# Domain層からインポート
41-
from domain.error_formatter import get_error_formatter
42-
from domain.exceptions import ConfigError
43-
from domain.types import ConfigData
40+
# Config層専用の型・例外・エラーメッセージ
41+
from .exceptions import ConfigError
42+
from .types import ConfigData
43+
from .error_messages import initialization_failed_message
4444

4545
# 内部コンポーネント
4646
from .config_loader import ConfigLoader
@@ -124,8 +124,7 @@ def __init__(self, plugin_root: Optional[Path] = None):
124124
self._directory_validator = self._config_validator
125125

126126
except (PermissionError, OSError) as e:
127-
formatter = get_error_formatter()
128-
raise ConfigError(formatter.config.initialization_failed("configuration", e)) from e
127+
raise ConfigError(initialization_failed_message("configuration", e)) from e
129128

130129
# =========================================================================
131130
# Context Manager Support

EpisodicRAG/scripts/config/cli.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,13 @@ def main(plugin_root: Optional[Path] = None) -> None:
4545
# デフォルト: JSON出力
4646
print(json.dumps(config.config, indent=2, ensure_ascii=False))
4747

48-
except FileNotFoundError as e:
49-
sys.stderr.write(f"[ERROR] {e}\n")
50-
sys.exit(1)
48+
except (FileNotFoundError, Exception) as e:
49+
# ConfigError やその他のエラーをキャッチ
50+
from .exceptions import ConfigError
51+
if isinstance(e, (FileNotFoundError, ConfigError)):
52+
sys.stderr.write(f"[ERROR] {e}\n")
53+
sys.exit(1)
54+
raise
5155

5256

5357
if __name__ == "__main__":

0 commit comments

Comments
 (0)