@@ -15,31 +15,98 @@ from application.validators import validate_dict, is_valid_list
1515
1616---
1717
18+ ## 目次
19+
20+ 1 . [ バリデーション(validators.py)] ( #バリデーションapplicationvalidatorspy )
21+ 2 . [ Shadow管理(shadow/)] ( #shadow管理applicationshadow )
22+ 3 . [ GrandDigest管理(grand/)] ( #granddigest管理applicationgrand )
23+ 4 . [ Finalize処理(finalize/)] ( #finalize処理applicationfinalize )
24+ 5 . [ 時間追跡(tracking/)] ( #時間追跡applicationtracking )
25+
26+ ---
27+
1828## バリデーション(application/validators.py)
1929
30+ データ型検証の共通関数群。重複する` isinstance ` チェックを統一し、一貫したエラーメッセージを提供。
31+
2032### validate_dict()
2133
2234``` python
2335def validate_dict (data : Any, context : str ) -> Dict[str , Any]
2436```
2537
26- データがdict であることを検証。違反時は`ValidationError` を送出。
38+ データがdict であることを検証。
39+
40+ | パラメータ | 型 | 説明 |
41+ | ---------- - | ------ | ------ |
42+ | `data` | `Any` | 検証対象のデータ |
43+ | `context` | `str ` | エラーメッセージに含める文脈情報(例: `" config.json" ` ) |
44+
45+ | 戻り値 | 説明 |
46+ | -------- | ------ |
47+ | `Dict[str , Any]` | 検証済みのdict |
48+
49+ | 例外 | 発生条件 |
50+ | ------ | ---------- |
51+ | `ValidationError` | `data` がdict でない場合 |
52+
53+ ** 使用例** :
54+ ```python
55+ from application.validators import validate_dict
56+
57+ raw_data = load_some_json()
58+ config = validate_dict(raw_data, " config.json" ) # 失敗時はValidationError
59+ ```
2760
2861### validate_list()
2962
3063``` python
3164def validate_list (data : Any, context : str ) -> List[Any]
3265```
3366
34- データがlist であることを検証。違反時は`ValidationError` を送出。
67+ データがlist であることを検証。
68+
69+ | パラメータ | 型 | 説明 |
70+ | ---------- - | ------ | ------ |
71+ | `data` | `Any` | 検証対象のデータ |
72+ | `context` | `str ` | エラーメッセージに含める文脈情報 |
73+
74+ | 戻り値 | 説明 |
75+ | -------- | ------ |
76+ | `List[Any]` | 検証済みのlist |
77+
78+ | 例外 | 発生条件 |
79+ | ------ | ---------- |
80+ | `ValidationError` | `data` がlist でない場合 |
3581
3682# ## validate_source_files()
3783
3884```python
3985def validate_source_files(files: Any, context: str = " source_files" ) -> List[str ]
4086```
4187
42- source_filesの形式を検証(list でNone / 空でないこと)。
88+ source_filesの形式を検証。
89+
90+ | パラメータ | 型 | デフォルト | 説明 |
91+ | ---------- - | ------ | ---------- - | ------ |
92+ | `files` | `Any` | - | 検証対象のデータ |
93+ | `context` | `str ` | `" source_files" ` | エラーメッセージに含める文脈情報 |
94+
95+ | 戻り値 | 説明 |
96+ | -------- | ------ |
97+ | `List[str ]` | 検証済みのファイルリスト |
98+
99+ | 例外 | 発生条件 |
100+ | ------ | ---------- |
101+ | `ValidationError` | `files` がNone 、list でない、または空の場合 |
102+
103+ ** 使用例** :
104+ ```python
105+ from application.validators import validate_source_files
106+
107+ files = validate_source_files(shadow_digest.get(" source_files" ))
108+ # files: ["L00001_xxx.txt", "L00002_yyy.txt"]
109+ ```
43110
44111### is_valid_dict() / is_valid_list()
45112
@@ -48,17 +115,52 @@ def is_valid_dict(data: Any) -> bool
48115def is_valid_list(data: Any) -> bool
49116```
50117
51- 例外を投げずにbool で型チェック。
118+ 例外を投げずにbool で型チェック。条件分岐での使用に適している。
119+
120+ | パラメータ | 型 | 説明 |
121+ | ---------- - | ------ | ------ |
122+ | `data` | `Any` | 検証対象のデータ |
123+
124+ | 戻り値 | 説明 |
125+ | -------- | ------ |
126+ | `bool ` | `data` が期待する型なら`True ` |
127+
128+ ** 使用例** :
129+ ```python
130+ from application.validators import is_valid_dict, is_valid_list
131+
132+ if is_valid_dict(data):
133+ process_dict(data)
134+ elif is_valid_list(data):
135+ process_list(data)
136+ ```
52137
53138### get_dict_or_default() / get_list_or_default()
54139
55140``` python
56- def get_dict_or_default(data: Any, default: Optional[Dict] = None ) -> Dict[str , Any]
57- def get_list_or_default(data: Any, default: Optional[List] = None ) -> List[Any]
141+ def get_dict_or_default (data : Any, default : Optional[Dict[ str , Any] ] = None ) -> Dict[str , Any]
142+ def get_list_or_default(data: Any, default: Optional[List[Any] ] = None ) -> List[Any]
58143```
59144
60145型が一致すればそのまま返し、不一致ならデフォルト値を返す。
61146
147+ | パラメータ | 型 | デフォルト | 説明 |
148+ | ---------- - | ------ | ---------- - | ------ |
149+ | `data` | `Any` | - | 検証対象のデータ |
150+ | `default` | `Optional[Dict]` / `Optional[List]` | `None ` (空のdict / list ) | 型不一致時の戻り値 |
151+
152+ | 戻り値 | 説明 |
153+ | -------- | ------ |
154+ | `Dict[str , Any]` / `List[Any]` | `data` が期待する型なら`data` 、そうでなければ`default` |
155+
156+ ** 使用例** :
157+ ```python
158+ from application.validators import get_dict_or_default
159+
160+ # Noneや不正な型でも安全に空dictを取得
161+ keywords = get_dict_or_default(raw_data.get(" keywords" ), {})
162+ ```
163+
62164---
63165
64166## Shadow管理(application/shadow/)
@@ -394,23 +496,111 @@ class DigestPersistence:
394496
395497### DigestTimesTracker
396498
397- last_digest_times.json管理クラス 。
499+ ` last_digest_times.json ` 管理クラス。各レベルの最終処理ファイル番号を追跡 。
398500
399501``` python
400502class DigestTimesTracker :
401503 def __init__ (self , config : DigestConfig): ...
402504```
403505
404- | メソッド | 説明 | 戻り値 |
405- | ---------| ------| --------|
406- | ` load_or_create() -> DigestTimesData ` | 最終ダイジェスト生成時刻を読み込み | DigestTimesData |
407- | ` extract_file_numbers(level, input_files) -> List[str] ` | ファイル名から連番を抽出(ゼロ埋め維持) | プレフィックス付き連番リスト |
408- | ` save(level, input_files=None) -> None ` | 最終生成時刻と処理済みファイル番号を保存 | - |
506+ ** コンストラクタ引数** :
507+
508+ | パラメータ | 型 | 説明 |
509+ | -----------| ------| ------|
510+ | ` config ` | ` DigestConfig ` | 設定オブジェクト |
511+
512+ ** インスタンス属性** :
513+
514+ | 属性 | 型 | 説明 |
515+ | ------| ------| ------|
516+ | ` last_digest_file ` | ` Path ` | ` {plugin_root}/.claude-plugin/last_digest_times.json ` |
517+ | ` template_file ` | ` Path ` | ` {plugin_root}/.claude-plugin/last_digest_times.template.json ` |
409518
410- ** save動作** :
519+ ---
520+
521+ #### load_or_create()
522+
523+ ``` python
524+ def load_or_create (self ) -> DigestTimesData
525+ ```
526+
527+ 最終ダイジェスト生成時刻を読み込む。存在しなければテンプレートから初期化。
528+
529+ | 戻り値 | 説明 |
530+ | -------- | ------ |
531+ | `DigestTimesData` | レベル別の最終処理情報 |
532+
533+ ** DigestTimesData構造** :
534+ ```python
535+ {
536+ " weekly" : {" timestamp" : " 2025-11-28T12:00:00" , " last_processed" : 5 },
537+ " monthly" : {" timestamp" : " " , " last_processed" : None },
538+ # ... 全8レベル
539+ }
540+ ```
541+
542+ ---
543+
544+ #### extract_file_numbers()
545+
546+ ``` python
547+ def extract_file_numbers (self , level : str , input_files : Optional[List[str ]]) -> List[str ]
548+ ```
549+
550+ ファイル名から連番を抽出(プレフィックス付き、ゼロ埋め維持)。
551+
552+ | パラメータ | 型 | 説明 |
553+ | ---------- - | ------ | ------ |
554+ | `level` | `str ` | ダイジェストレベル(将来の拡張用) |
555+ | `input_files` | `Optional[List[str ]]` | ファイル名のリスト |
556+
557+ | 戻り値 | 説明 |
558+ | -------- | ------ |
559+ | `List[str ]` | 抽出・フォーマットされた連番リスト(無効な入力は空リスト) |
560+
561+ ** 使用例** :
562+ ```python
563+ tracker = DigestTimesTracker(config)
564+ numbers = tracker.extract_file_numbers(" weekly" , [" L00001_xxx.txt" , " L00005_yyy.txt" ])
565+ # numbers: ["L00001", "L00005"]
566+ ```
567+
568+ ---
569+
570+ #### save()
571+
572+ ``` python
573+ def save (self , level : str , input_files : Optional[List[str ]] = None ) -> None
574+ ```
575+
576+ 最終生成時刻と最新処理済みファイル番号を保存。
577+
578+ | パラメータ | 型 | デフォルト | 説明 |
579+ | ---------- - | ------ | ---------- - | ------ |
580+ | `level` | `str ` | - | ダイジェストレベル |
581+ | `input_files` | `Optional[List[str ]]` | `None ` | 処理したファイル名のリスト |
582+
583+ ** 動作フロー** :
4115841 . 既存データを読み込み
4125852 . `input_files` から最後のファイル番号を抽出
413- 3 . ` {level: {timestamp: ISO8601, last_processed: "W0005"}} ` 形式で保存
586+ 3 . 現在時刻とともに保存
587+
588+ ** 保存形式** :
589+ ```python
590+ {
591+ " weekly" : {
592+ " timestamp" : " 2025-11-28T12:00:00" ,
593+ " last_processed" : 5 # 最後に処理したファイル番号(int)
594+ }
595+ }
596+ ```
597+
598+ ** 使用例** :
599+ ``` python
600+ tracker = DigestTimesTracker(config)
601+ tracker.save(" weekly" , [" L00001_xxx.txt" , " L00002_yyy.txt" , " L00005_zzz.txt" ])
602+ # last_processed = 5
603+ ```
414604
415605---
416606
0 commit comments