mangubee Claude commited on
Commit
fa82033
·
1 Parent(s): fed2514

feat: standardize logging with console + file separation

Browse files

- Console: Compressed status workflow ([plan] ✓, [execute] ✓, [answer] ✓)
- Files: log/ folder with full LLM context and transcripts
- Update CLAUDE.md with logging standard
- Add log/ to .gitignore

Separates status updates (console) from debugging details (log/ files).

Co-Authored-By: Claude <noreply@anthropic.com>

Files changed (4) hide show
  1. .gitignore +3 -0
  2. CLAUDE.md +26 -1
  3. src/agent/llm_client.py +4 -4
  4. src/tools/youtube.py +6 -6
.gitignore CHANGED
@@ -37,6 +37,9 @@ input/*
37
  # Runtime cache (not in git, served via app download)
38
  _cache/
39
 
 
 
 
40
  # Testing
41
  .pytest_cache/
42
  .coverage
 
37
  # Runtime cache (not in git, served via app download)
38
  _cache/
39
 
40
+ # Runtime logs (not in git, for debugging and analysis)
41
+ log/
42
+
43
  # Testing
44
  .pytest_cache/
45
  .coverage
CLAUDE.md CHANGED
@@ -1,4 +1,29 @@
1
  # Project-Specific Instructions
2
 
3
- [Leave empty unless project requires special behavior]
4
  [Inherits all rules from ~/.claude/CLAUDE.md]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # Project-Specific Instructions
2
 
 
3
  [Inherits all rules from ~/.claude/CLAUDE.md]
4
+
5
+ ## Logging Standard
6
+
7
+ **Console Output (Status Workflow):**
8
+ - **Compressed status updates:** `[node] ✓ result` or `[node] ✗ error`
9
+ - **Progress indicators:** `[1/1] Processing task_id`, `[1/20]` for batch
10
+ - **Key milestones only:** 3-4 statements vs verbose logs
11
+ - **Node labels:** `[plan]`, `[execute]`, `[answer]` with success/failure
12
+
13
+ **Log Files (log/ folder):**
14
+ - **llm_context_TIMESTAMP.txt** - Full LLM prompts, evidence, answers for debugging
15
+ - **{video_id}_transcript.txt** - Raw transcripts from YouTube/Whisper
16
+ - **Purpose:** Post-run analysis, context preservation, audit trail
17
+ - **Format:** Structured headers with timestamp, question, evidence items, full content
18
+
19
+ **Log Format Examples:**
20
+ ```
21
+ [plan] ✓ 660 chars
22
+ [execute] 1 tool(s) selected
23
+ [1/1] youtube_transcript ✓
24
+ [execute] 1 tools, 1 evidence
25
+ [answer] ✓ 3
26
+ Context saved to: log/llm_context_20260113_022706.txt
27
+ ```
28
+
29
+ **Note:** Explicit user request overrides global rule about "no logs/ folder"
src/agent/llm_client.py CHANGED
@@ -1108,16 +1108,16 @@ Examples of bad answers (too verbose):
1108
  Extract the factoid answer from the evidence above. Return only the factoid, nothing else."""
1109
 
1110
  # ============================================================================
1111
- # SAVE LLM CONTEXT TO CACHE - For debugging and comparison
1112
  # ============================================================================
1113
  from pathlib import Path
1114
  import datetime
1115
 
1116
- cache_dir = Path("_cache")
1117
- cache_dir.mkdir(exist_ok=True)
1118
 
1119
  timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
1120
- context_file = cache_dir / f"llm_context_{timestamp}.txt"
1121
 
1122
  with open(context_file, "w", encoding="utf-8") as f:
1123
  f.write("=" * 80 + "\n")
 
1108
  Extract the factoid answer from the evidence above. Return only the factoid, nothing else."""
1109
 
1110
  # ============================================================================
1111
+ # SAVE LLM CONTEXT TO LOG - For debugging and comparison
1112
  # ============================================================================
1113
  from pathlib import Path
1114
  import datetime
1115
 
1116
+ log_dir = Path("log")
1117
+ log_dir.mkdir(exist_ok=True)
1118
 
1119
  timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
1120
+ context_file = log_dir / f"llm_context_{timestamp}.txt"
1121
 
1122
  with open(context_file, "w", encoding="utf-8") as f:
1123
  f.write("=" * 80 + "\n")
src/tools/youtube.py CHANGED
@@ -54,7 +54,7 @@ logger = logging.getLogger(__name__)
54
 
55
  def save_transcript_to_cache(video_id: str, text: str, source: str) -> None:
56
  """
57
- Save transcript to _cache folder for debugging.
58
 
59
  Args:
60
  video_id: YouTube video ID
@@ -62,10 +62,10 @@ def save_transcript_to_cache(video_id: str, text: str, source: str) -> None:
62
  source: "api" or "whisper"
63
  """
64
  try:
65
- cache_dir = Path("_cache")
66
- cache_dir.mkdir(exist_ok=True)
67
 
68
- cache_file = cache_dir / f"{video_id}_transcript.txt"
69
  with open(cache_file, "w", encoding="utf-8") as f:
70
  f.write(f"# YouTube Transcript\n")
71
  f.write(f"# Video ID: {video_id}\n")
@@ -74,9 +74,9 @@ def save_transcript_to_cache(video_id: str, text: str, source: str) -> None:
74
  f.write(f"# Generated: {__import__('datetime').datetime.now().isoformat()}\n")
75
  f.write(f"\n{text}\n")
76
 
77
- logger.info(f"Transcript saved to cache: {cache_file}")
78
  except Exception as e:
79
- logger.warning(f"Failed to save transcript to cache: {e}")
80
 
81
 
82
  # ============================================================================
 
54
 
55
  def save_transcript_to_cache(video_id: str, text: str, source: str) -> None:
56
  """
57
+ Save transcript to log/ folder for debugging.
58
 
59
  Args:
60
  video_id: YouTube video ID
 
62
  source: "api" or "whisper"
63
  """
64
  try:
65
+ log_dir = Path("log")
66
+ log_dir.mkdir(exist_ok=True)
67
 
68
+ cache_file = log_dir / f"{video_id}_transcript.txt"
69
  with open(cache_file, "w", encoding="utf-8") as f:
70
  f.write(f"# YouTube Transcript\n")
71
  f.write(f"# Video ID: {video_id}\n")
 
74
  f.write(f"# Generated: {__import__('datetime').datetime.now().isoformat()}\n")
75
  f.write(f"\n{text}\n")
76
 
77
+ logger.info(f"Transcript saved: {cache_file}")
78
  except Exception as e:
79
+ logger.warning(f"Failed to save transcript: {e}")
80
 
81
 
82
  # ============================================================================