Skip to content

Commit f68dab9

Browse files
fix(mcp): reversible text truncation; bound expand_query floor
Address truncation-audit findings so every markdown-default response stays bounded and recoverable: - S4: tracedecay_files and tracedecay_type_hierarchy no longer clip oversized output irreversibly. New render::truncate_text_with_handle stores the full body and returns the markdown truncation envelope with an rh_ handle (delegates to truncated_markdown_with_handle; no duplicated logic). - S3: lcm_expand_query_tool_json's format:"json"+needs_synthesis path could emit an unbounded payload when even the Minimal compaction tier overflowed. New bounded_lcm_expand_query_floor_text enforces a floor: stores a retrieval handle (surfaced as response_handle for the Hermes bridge) and keeps the contract keys (status, needs_synthesis, bounded answer/prompt, rebuilt synthesis_prompt) while zeroing unbounded arrays with *_truncated markers. - S5: LCM preflight/expand_query compaction tiers now call observe_response_truncation so those truncations show up in metrics. - Drop unused LCM_GREP_SNIPPET_CHARS (lcm_grep hits are already bounded). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 162161d commit f68dab9

3 files changed

Lines changed: 373 additions & 14 deletions

File tree

src/mcp/tools/handlers/info.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::storage::{ProjectPath, StorageMode, StoreKind};
1313
use crate::tracedecay::{BranchDiagnostics, TraceDecay};
1414
use crate::types::{NodeKind, Visibility};
1515

16-
use super::super::render::{self, truncate_response, Md};
16+
use super::super::render::{self, Md};
1717
use super::super::ToolResult;
1818
use super::support::{effective_path, filter_by_scope, require_node_id, unique_file_paths};
1919

@@ -632,7 +632,7 @@ pub(super) async fn handle_files(
632632

633633
Ok(ToolResult::new(
634634
json!({
635-
"content": [{ "type": "text", "text": truncate_response(&output) }]
635+
"content": [{ "type": "text", "text": render::truncate_text_with_handle(Some(cg.project_root()), &output) }]
636636
}),
637637
touched_files,
638638
))
@@ -1535,7 +1535,7 @@ pub(super) async fn handle_type_hierarchy(cg: &TraceDecay, args: Value) -> Resul
15351535

15361536
let touched_files = unique_file_paths(all_files.iter().map(std::string::String::as_str));
15371537
Ok(ToolResult::new(
1538-
json!({"content": [{"type": "text", "text": truncate_response(&output)}]}),
1538+
json!({"content": [{"type": "text", "text": render::truncate_text_with_handle(Some(cg.project_root()), &output)}]}),
15391539
touched_files,
15401540
))
15411541
}

0 commit comments

Comments
 (0)