Skip to content

Commit ff53571

Browse files
web-flowclaude
andcommitted
docs: 教材化プロジェクト - Config層独立性の整合性修正
- DESIGN_DECISIONS.md: レイヤー構造図を4層+Config層(完全独立)に分離 - LEARNING_PATH.md: Config層の独立性を学習ポイントとして追記 - scripts/README.md: 依存関係ルールをARCHITECTURE.mdと整合 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 7745bba commit ff53571

6 files changed

Lines changed: 57 additions & 28 deletions

File tree

EpisodicRAG/docs/dev/DESIGN_DECISIONS.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@
8080

8181
## レイヤー構造
8282

83+
### Clean Architecture 4層
84+
8385
```
8486
┌─────────────────────────────────────────────────────────┐
8587
│ Interfaces Layer │
@@ -100,19 +102,27 @@
100102
└─────────────────────────────────────────────────────────┘
101103
↓ 依存
102104
┌─────────────────────────────────────────────────────────┐
103-
│ Config Layer │
104-
│ (facade.py, threshold_provider.py, path_resolver.py) │
105-
│ 設定管理、パス解決 │
106-
└─────────────────────────────────────────────────────────┘
107-
↓ 依存
108-
┌─────────────────────────────────────────────────────────┐
109105
│ Domain Layer │
110106
│ (types.py, constants.py, exceptions.py, protocols.py) │
111107
│ ビジネスルール、型定義、例外(外部依存なし) │
112108
└─────────────────────────────────────────────────────────┘
113109
```
114110

115-
**重要な制約**: 依存は常に下方向のみ。上位層が下位層に依存し、逆は許可されない。
111+
### Config層(完全独立)
112+
113+
```
114+
┌─────────────────────────────────────────────────────────┐
115+
│ Config Layer │
116+
│ (facade.py, threshold_provider.py, path_resolver.py) │
117+
│ 設定管理、パス解決 │
118+
│ ※ 4層とは独立 - domain/を含む全層に依存しない │
119+
└─────────────────────────────────────────────────────────┘
120+
```
121+
122+
**重要な制約**:
123+
- 4層は常に下方向のみ依存。上位層が下位層に依存し、逆は許可されない
124+
- Config層は**完全独立**であり、domain/を含むすべての層に依存しない
125+
- 詳細: [ARCHITECTURE.md](ARCHITECTURE.md#clean-architecture)
116126

117127
---
118128

EpisodicRAG/docs/dev/LEARNING_PATH.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
## このプロジェクトで学べること
1010

11-
### 1. Clean Architecture(4層構造)
11+
### 1. Clean Architecture(4層構造 + Config層
1212

1313
EpisodicRAGは依存関係ルールに基づく4層構造を採用しています。
1414

@@ -18,12 +18,21 @@ EpisodicRAGは依存関係ルールに基づく4層構造を採用していま
1818
| Infrastructure | `scripts/infrastructure/` | 外部I/Oの抽象化(JSON、ファイル、ログ) |
1919
| Application | `scripts/application/` | ユースケースの実装 |
2020
| Interfaces | `scripts/interfaces/` | エントリーポイント |
21+
| **Config** | `scripts/config/` | **完全独立** - 設定管理、パス解決 |
2122

2223
**学習ポイント**:
2324
- `scripts/domain/` を読む → 外部依存のない純粋な定義を理解
2425
- `scripts/application/` を読む → 依存関係ルールの実践を確認
2526
- 参照: [ARCHITECTURE.md](ARCHITECTURE.md#clean-architecture)
2627

28+
> ⚠️ **Config層の独立性**(重要な学習ポイント)
29+
>
30+
> Config層は4層とは別に**完全独立**しており、domain/を含む全層に依存しません。
31+
> これはプラグインとして単独ロード可能にするための設計判断です。
32+
> 「なぜ独立させるか」を学ぶことで、アーキテクチャ判断の実践例を理解できます。
33+
>
34+
> 参照: [ARCHITECTURE.md](ARCHITECTURE.md#clean-architecture)
35+
2736
### 2. Single Source of Truth (SSoT)
2837

2938
情報の重複を避け、一元管理する原則を徹底しています。

EpisodicRAG/scripts/README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,19 @@ domain/ ← 何にも依存しない(純粋なビジネスロジッ
3636
3737
infrastructure/ ← domain/ のみ
3838
39-
config/ ← domain/ + infrastructure/(設定管理層)
40-
41-
application/ ← domain/ + infrastructure/ + config/
39+
application/ ← domain/ + infrastructure/
4240
4341
interfaces/ ← application/
42+
43+
config/ ← 何にも依存しない(完全独立)
4444
```
4545

46-
> **Note**: `config/` 層は設定管理を担当し、`DigestConfig` クラスやパス解決、
47-
> 閾値管理などを提供します。`application/` 層が設定にアクセスする際は
48-
> この層を経由します。
46+
> ⚠️ **CRITICAL: Config層の独立性**
47+
>
48+
> `config/` パッケージは **domain/ を含む他のすべての層から完全に独立** しています。
49+
> これは `digest-config` スキルがClaudeプラグインとして単独でロード可能である必要があるためです。
50+
>
51+
> 詳細: [ARCHITECTURE.md](../docs/dev/ARCHITECTURE.md#clean-architecture)
4952
5053
---
5154

EpisodicRAG/scripts/application/shadow/cascade_processor.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747

4848
from domain.types import LevelHierarchyEntry, OverallDigestData
4949
from domain.validators import is_valid_overall_digest
50-
from infrastructure import get_structured_logger, log_info
50+
from infrastructure import get_structured_logger
5151

5252
# 構造化ロガー
5353
_logger = get_structured_logger(__name__)
@@ -111,7 +111,7 @@ def get_shadow_digest_for_level(self, level: str) -> Optional[OverallDigestData]
111111
"""
112112
指定レベルのShadowダイジェストを取得
113113
114-
finalize_from_shadow.pyで使用: これがRegularDigestの内容になります
114+
finalize_from_shadow.pyで使用: ShadowGrandDigestからoverall_digestを取得
115115
116116
Args:
117117
level: レベル名
@@ -128,7 +128,7 @@ def get_shadow_digest_for_level(self, level: str) -> Optional[OverallDigestData]
128128
)
129129

130130
if not is_valid_overall_digest(overall_digest):
131-
log_info(f"No shadow digest for level: {level}")
131+
_logger.info(f"No shadow digest for level: {level}")
132132
return None
133133

134134
# is_valid_overall_digest は TypeGuard なので、
@@ -149,11 +149,11 @@ def promote_shadow_to_grand(self, level: str) -> None:
149149
digest = self.get_shadow_digest_for_level(level)
150150

151151
if not digest:
152-
log_info(f"No shadow digest to promote for level: {level}")
152+
_logger.info(f"No shadow digest to promote for level: {level}")
153153
return
154154

155155
file_count = len(digest.get("source_files", []))
156-
log_info(f"Shadow digest ready for promotion: {file_count} file(s)")
156+
_logger.info(f"Shadow digest ready for promotion: {file_count} file(s)")
157157
# 実際の昇格処理はfinalize_from_shadow.pyで実行される
158158

159159
def clear_shadow_level(self, level: str) -> None:
@@ -171,7 +171,7 @@ def clear_shadow_level(self, level: str) -> None:
171171
)
172172

173173
self.shadow_io.save(shadow_data)
174-
log_info(f"Cleared ShadowGrandDigest for level: {level}")
174+
_logger.info(f"Cleared ShadowGrandDigest for level: {level}")
175175

176176
def cascade_update_on_digest_finalize(self, level: str) -> None:
177177
"""
@@ -186,7 +186,7 @@ def cascade_update_on_digest_finalize(self, level: str) -> None:
186186
Args:
187187
level: レベル名
188188
"""
189-
log_info(f"[Step 3] ShadowGrandDigest cascade for level: {level}")
189+
_logger.info(f"[Step 3] ShadowGrandDigest cascade for level: {level}")
190190
_logger.state("cascade_update", starting_for_level=level)
191191

192192
# 1. Shadow → Grand 昇格の確認
@@ -201,17 +201,17 @@ def cascade_update_on_digest_finalize(self, level: str) -> None:
201201
_logger.file_op(f"find_new_files({next_level})", found=len(new_files))
202202

203203
if new_files:
204-
log_info(f"Found {len(new_files)} new file(s) for {next_level}:")
204+
_logger.info(f"Found {len(new_files)} new file(s) for {next_level}:")
205205
file_names = [f.name for f in new_files[:5]]
206206
suffix = "..." if len(new_files) > 5 else ""
207207
_logger.file_op("new_files", names=f"{file_names}{suffix}")
208208

209209
# 3. 次のレベルのShadowに増分追加
210210
self.file_appender.add_files_to_shadow(next_level, new_files)
211211
else:
212-
log_info(f"No next level for {level} (top level)")
212+
_logger.info(f"No next level for {level} (top level)")
213213

214214
# 4. 現在のレベルのShadowをクリア
215215
self.clear_shadow_level(level)
216216

217-
log_info(f"[Step 3] Cascade completed for level: {level}")
217+
_logger.info(f"[Step 3] Cascade completed for level: {level}")

EpisodicRAG/scripts/application/shadow/file_detector.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,5 @@ def find_new_files(self, level: str) -> List[Path]:
8989
# 初回は全ファイルを検出
9090
return all_files
9191

92-
# max_file_number is already int (from DigestTimesData)
93-
max_num = max_file_number
94-
9592
# 統一関数を使用してフィルタリング
96-
return filter_files_after(all_files, max_num)
93+
return filter_files_after(all_files, max_file_number)

EpisodicRAG/scripts/application/validators.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@
2727
# =============================================================================
2828
# 公開API(後方互換性維持)
2929
# =============================================================================
30+
#
31+
# NOTE: これらの関数はdomain層の検証関数への薄いラッパーです。
32+
# domain.validation および domain.validators に直接アクセスすることも可能ですが、
33+
# 既存コードとの後方互換性を維持するためにこのモジュールを提供しています。
34+
#
35+
# 新規コードでは、用途に応じて以下を直接使用することを推奨:
36+
# - domain.validation.validate_type() - 型検証(例外を投げる)
37+
# - domain.validators.is_valid_type() - 型チェック(boolを返す)
38+
# - domain.validators.get_or_default() - デフォルト値付き取得
39+
#
3040

3141

3242
def validate_dict(data: Any, context: str) -> Dict[str, Any]:

0 commit comments

Comments
 (0)