fix(engine): demote trace/reflection logging from info to debug

INFO-level log output from background tasks (trace analysis, reflection)
corrupts the REPL terminal UI. The trace summary, issue warnings, and
reflection doc previews were printing mid-approval-card, breaking the
interactive display.

Fix: all logging in trace.rs changed from info!/warn! to debug!/warn!.
Trace analysis and reflection results now only show when
RUST_LOG=ironclaw_engine=debug is set.

Also added logging discipline rule to global CLAUDE.md:
- info! → user-facing status the REPL intentionally renders
- debug! → internal diagnostics (traces, reflection, engine internals)
- Background tasks must NEVER use info! — it breaks the TUI

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
2026-03-23 21:14:08 -07:00
co-authored by Claude Opus 4.6
parent e82dcbd5e6
commit c1163f41fc
2 changed files with 7 additions and 6 deletions
+1
View File
@@ -24,6 +24,7 @@ E2E tests: see `tests/e2e/CLAUDE.md`.
- Prefer strong types over strings (enums, newtypes)
- Keep functions focused, extract helpers when logic is reused
- Comments for non-obvious logic only
- **Logging levels matter for REPL/TUI**: `info!` and `warn!` output appears in the REPL and corrupts the terminal UI. Use `debug!` for internal diagnostics (trace analysis, reflection results, engine internals). Reserve `info!` for user-facing status that the REPL intentionally renders. Background tasks (reflection, trace analysis) must NEVER use `info!` — it breaks the interactive display.
## Architecture
+6 -6
View File
@@ -10,7 +10,7 @@ use std::path::PathBuf;
use chrono::Utc;
use serde::Serialize;
use tracing::{info, warn};
use tracing::{debug, warn};
use crate::types::event::ThreadEvent;
use crate::types::thread::{Thread, ThreadId, ThreadState};
@@ -125,7 +125,7 @@ pub fn write_trace(trace: &ExecutionTrace) -> Option<PathBuf> {
match serde_json::to_string_pretty(trace) {
Ok(json) => match std::fs::write(&path, json) {
Ok(()) => {
info!(path = %path.display(), "Execution trace written");
debug!(path = %path.display(), "Execution trace written");
Some(path)
}
Err(e) => {
@@ -158,7 +158,7 @@ pub fn attach_reflection(trace: &mut ExecutionTrace, result: &crate::reflection:
/// Print a summary of the trace to the log.
pub fn log_trace_summary(trace: &ExecutionTrace) {
info!(
debug!(
thread_id = %trace.thread_id,
goal = %trace.goal,
state = ?trace.final_state,
@@ -184,7 +184,7 @@ pub fn log_trace_summary(trace: &ExecutionTrace) {
"WARNING: {}",
issue.description
),
IssueSeverity::Info => info!(
IssueSeverity::Info => debug!(
category = %issue.category,
step = ?issue.step,
"NOTE: {}",
@@ -194,7 +194,7 @@ pub fn log_trace_summary(trace: &ExecutionTrace) {
}
if let Some(ref refl) = trace.reflection {
info!(
debug!(
thread_id = %trace.thread_id,
docs = refl.docs.len(),
tokens = refl.tokens_used,
@@ -207,7 +207,7 @@ pub fn log_trace_summary(trace: &ExecutionTrace) {
} else {
""
};
info!(
debug!(
doc_type = %doc.doc_type,
title = %doc.title,
" {preview}{truncated}"