Polish status and config output for operator readability

Reformat /status and /config into sectioned reports with stable labels so the CLI surfaces read more like a usable operator console and less like dense debug strings. This improves discoverability and parity feel without changing the underlying data model or inventing fake settings behavior.

Constraint: Output polish must preserve the exact locally discoverable facts already exposed by the CLI
Rejected: Add interactive /clear confirmation first | wording/layout polish was cleaner, lower-risk, and touched fewer control-flow paths
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep CLI reports sectioned and label-stable so future tests can assert on intent rather than fragile token ordering
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace
Not-tested: Manual terminal-width UX review for very long paths or merged JSON payloads
This commit is contained in:
Yeachan-Heo
2026-03-31 20:41:39 +00:00
parent 2ad2ec087f
commit b510387045

View File

@@ -633,34 +633,46 @@ fn format_status_report(
permission_mode: &str, permission_mode: &str,
context: &StatusContext, context: &StatusContext,
) -> String { ) -> String {
let mut lines = vec![format!( [
"status: model={model} permission_mode={permission_mode} messages={} turns={} estimated_tokens={} latest_tokens={} cumulative_input_tokens={} cumulative_output_tokens={} cumulative_total_tokens={}", format!(
usage.message_count, "Status
usage.turns, Model {model}
usage.estimated_tokens, Permission mode {permission_mode}
usage.latest.total_tokens(), Messages {}
usage.cumulative.input_tokens, Turns {}
usage.cumulative.output_tokens, Estimated tokens {}",
usage.cumulative.total_tokens(), usage.message_count, usage.turns, usage.estimated_tokens,
)]; ),
lines.push(format!(" cwd {}", context.cwd.display())); format!(
lines.push(format!( "Usage
" session {}", Latest total {}
context.session_path.as_ref().map_or_else( Cumulative input {}
|| "live-repl".to_string(), Cumulative output {}
|path| path.display().to_string() Cumulative total {}",
) usage.latest.total_tokens(),
)); usage.cumulative.input_tokens,
lines.push(format!( usage.cumulative.output_tokens,
" config loaded {}/{} files", usage.cumulative.total_tokens(),
context.loaded_config_files, context.discovered_config_files ),
)); format!(
lines.push(format!( "Workspace
" memory {} instruction files", Cwd {}
context.memory_file_count Session {}
)); Config files loaded {}/{}
lines.join( Memory files {}",
context.cwd.display(),
context.session_path.as_ref().map_or_else(
|| "live-repl".to_string(),
|path| path.display().to_string()
),
context.loaded_config_files,
context.discovered_config_files,
context.memory_file_count,
),
]
.join(
" "
", ",
) )
} }
@@ -671,11 +683,18 @@ fn render_config_report() -> Result<String, Box<dyn std::error::Error>> {
let discovered = loader.discover(); let discovered = loader.discover();
let runtime_config = loader.load()?; let runtime_config = loader.load()?;
let mut lines = vec![format!( let mut lines = vec![
"config: loaded_files={} merged_keys={}", format!(
runtime_config.loaded_entries().len(), "Config
runtime_config.merged().len() Working directory {}
)]; Loaded files {}
Merged keys {}",
cwd.display(),
runtime_config.loaded_entries().len(),
runtime_config.merged().len()
),
"Discovered files".to_string(),
];
for entry in discovered { for entry in discovered {
let source = match entry.source { let source = match entry.source {
ConfigSource::User => "user", ConfigSource::User => "user",
@@ -696,7 +715,8 @@ fn render_config_report() -> Result<String, Box<dyn std::error::Error>> {
entry.path.display() entry.path.display()
)); ));
} }
lines.push(format!(" merged {}", runtime_config.as_json().render())); lines.push("Merged JSON".to_string());
lines.push(format!(" {}", runtime_config.as_json().render()));
Ok(lines.join( Ok(lines.join(
" "
", ",
@@ -1305,15 +1325,24 @@ mod tests {
memory_file_count: 4, memory_file_count: 4,
}, },
); );
assert!(status.contains("model=claude-sonnet")); assert!(status.contains("Status"));
assert!(status.contains("permission_mode=workspace-write")); assert!(status.contains("Model claude-sonnet"));
assert!(status.contains("messages=7")); assert!(status.contains("Permission mode workspace-write"));
assert!(status.contains("latest_tokens=10")); assert!(status.contains("Messages 7"));
assert!(status.contains("cumulative_total_tokens=31")); assert!(status.contains("Latest total 10"));
assert!(status.contains("cwd /tmp/project")); assert!(status.contains("Cumulative total 31"));
assert!(status.contains("session session.json")); assert!(status.contains("Cwd /tmp/project"));
assert!(status.contains("config loaded 2/3 files")); assert!(status.contains("Session session.json"));
assert!(status.contains("memory 4 instruction files")); assert!(status.contains("Config files loaded 2/3"));
assert!(status.contains("Memory files 4"));
}
#[test]
fn config_report_uses_sectioned_layout() {
let report = super::render_config_report().expect("config report should render");
assert!(report.contains("Config"));
assert!(report.contains("Discovered files"));
assert!(report.contains("Merged JSON"));
} }
#[test] #[test]