mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-07 08:27:12 +00:00
Redesign compact and summary:high preamble rendering
Compact mode now renders nested-bullet summaries with handler-specific sub-items (script: command/stdout/stderr; codergen: model/tokens/files) under a ## Completed stages heading. Summary:high renders per-stage ## Stage sections with full detail and a ## Current context table. Also captures script.stderr in context_updates for both success and failure branches, and improves context filtering across all modes to exclude engine keys (graph.*, thread.*, response.*, last_stage, etc.). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
92a4c5e506
commit
b11c92bf66
3 changed files with 1011 additions and 156 deletions
|
|
@ -132,6 +132,9 @@ impl Handler for ScriptHandler {
|
|||
outcome
|
||||
.context_updates
|
||||
.insert("tool.output".to_string(), serde_json::json!(stdout));
|
||||
outcome
|
||||
.context_updates
|
||||
.insert("script.stderr".to_string(), serde_json::json!(stderr));
|
||||
outcome.notes = Some(format!("Script completed: {script}"));
|
||||
Ok(outcome)
|
||||
} else {
|
||||
|
|
@ -143,7 +146,11 @@ impl Handler for ScriptHandler {
|
|||
} else {
|
||||
format!("Script failed: {}", stderr.trim())
|
||||
};
|
||||
Ok(Outcome::fail(reason))
|
||||
let mut outcome = Outcome::fail(reason);
|
||||
outcome
|
||||
.context_updates
|
||||
.insert("script.stderr".to_string(), serde_json::json!(stderr));
|
||||
Ok(outcome)
|
||||
}
|
||||
}
|
||||
Err(e) => Ok(Outcome::fail(e.to_string())),
|
||||
|
|
@ -210,6 +217,8 @@ mod tests {
|
|||
assert!(outcome.notes.as_deref().unwrap().contains("echo hello"));
|
||||
let script_output = outcome.context_updates.get("script.output").unwrap();
|
||||
assert!(script_output.as_str().unwrap().contains("hello"));
|
||||
let script_stderr = outcome.context_updates.get("script.stderr").unwrap();
|
||||
assert_eq!(script_stderr.as_str().unwrap(), "");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -544,6 +553,31 @@ mod tests {
|
|||
assert!(script_output.as_str().unwrap().contains("legacy"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn script_handler_captures_stderr() {
|
||||
let handler = ScriptHandler;
|
||||
let mut node = Node::new("script_node");
|
||||
node.attrs.insert(
|
||||
"script".to_string(),
|
||||
AttrValue::String("echo out && echo err >&2".to_string()),
|
||||
);
|
||||
let context = Context::new();
|
||||
let graph = Graph::new("test");
|
||||
let logs_root = tempfile::tempdir().unwrap();
|
||||
|
||||
let outcome = handler
|
||||
.execute(&node, &context, &graph, logs_root.path(), &make_services())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(outcome.status, StageStatus::Success);
|
||||
let script_stderr = outcome.context_updates.get("script.stderr").unwrap();
|
||||
assert!(
|
||||
script_stderr.as_str().unwrap().contains("err"),
|
||||
"script.stderr should contain 'err', got: {:?}",
|
||||
script_stderr
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn tool_output_context_key_dual_write() {
|
||||
let handler = ScriptHandler;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -4599,7 +4599,7 @@ async fn fidelity_compact_preamble_includes_completed_stages_and_context() {
|
|||
"compact preamble should contain the goal"
|
||||
);
|
||||
assert!(
|
||||
step_b_preamble.contains("Completed stages:"),
|
||||
step_b_preamble.contains("## Completed stages"),
|
||||
"compact preamble should include completed stages section"
|
||||
);
|
||||
assert!(
|
||||
|
|
@ -4672,10 +4672,17 @@ async fn fidelity_summary_low_excludes_context_values_in_pipeline() {
|
|||
|
||||
let preambles_med = captures_med.preambles.lock().unwrap();
|
||||
let med_preamble = &preambles_med[1].1;
|
||||
// summary:medium should include "Context values:" section (graph.goal is always set)
|
||||
// summary:medium should include stage details (unlike summary:low which omits them)
|
||||
assert!(
|
||||
med_preamble.contains("Context values:"),
|
||||
"summary:medium preamble should include context values section"
|
||||
med_preamble.contains("step_a"),
|
||||
"summary:medium preamble should include completed stage step_a"
|
||||
);
|
||||
// Verify medium and low differ: medium shows more recent stages
|
||||
let preambles_low = captures_low.preambles.lock().unwrap();
|
||||
let low_preamble = &preambles_low[1].1;
|
||||
assert!(
|
||||
!low_preamble.contains("## Context"),
|
||||
"summary:low preamble should not include context section"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -6729,11 +6736,12 @@ async fn run_fidelity_prompt_pipeline(fidelity: &str) -> String {
|
|||
async fn fidelity_prompt_compact() {
|
||||
let prompt = run_fidelity_prompt_pipeline("compact").await;
|
||||
|
||||
// Preamble should contain goal, completed stages, and context values
|
||||
// Preamble should contain goal, completed stages with handler details, and context
|
||||
assert!(prompt.contains("Validate the build"), "compact: should contain goal");
|
||||
assert!(prompt.contains("Completed stages:"), "compact: should list completed stages");
|
||||
assert!(prompt.contains("run_tests"), "compact: should mention run_tests node");
|
||||
assert!(prompt.contains("Context values:"), "compact: should include context values section");
|
||||
assert!(prompt.contains("## Completed stages"), "compact: should list completed stages");
|
||||
assert!(prompt.contains("**run_tests**"), "compact: should mention run_tests node in bold");
|
||||
assert!(prompt.contains("Script:"), "compact: should show script sub-item for run_tests");
|
||||
assert!(prompt.contains("Stdout:"), "compact: should show stdout sub-item for run_tests");
|
||||
|
||||
// Original prompt at the end
|
||||
assert!(
|
||||
|
|
@ -6779,7 +6787,7 @@ async fn fidelity_prompt_summary_medium() {
|
|||
// summary:medium includes goal, stages, and context values
|
||||
assert!(prompt.contains("Validate the build"), "summary:medium: should contain goal");
|
||||
assert!(prompt.contains("run_tests"), "summary:medium: should mention run_tests");
|
||||
assert!(prompt.contains("Context values:"), "summary:medium: should include context values");
|
||||
assert!(prompt.contains("## Context"), "summary:medium: should include context section");
|
||||
|
||||
// Original prompt at the end
|
||||
assert!(
|
||||
|
|
@ -6792,10 +6800,11 @@ async fn fidelity_prompt_summary_medium() {
|
|||
async fn fidelity_prompt_summary_high() {
|
||||
let prompt = run_fidelity_prompt_pipeline("summary:high").await;
|
||||
|
||||
// summary:high includes goal, all stages, context values
|
||||
// summary:high includes goal, all stages as ## Stage headings
|
||||
assert!(prompt.contains("Validate the build"), "summary:high: should contain goal");
|
||||
assert!(prompt.contains("run_tests"), "summary:high: should mention run_tests");
|
||||
assert!(prompt.contains("Context values:"), "summary:high: should include context values");
|
||||
assert!(prompt.contains("## Stage: run_tests"), "summary:high: should have stage heading for run_tests");
|
||||
assert!(prompt.contains("## Stage: start"), "summary:high: should have stage heading for start");
|
||||
assert!(prompt.contains("Pipeline progress:"), "summary:high: should show pipeline progress");
|
||||
|
||||
// Original prompt at the end
|
||||
assert!(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue