fix(cli): render spec-required panels in agents plan rollback rich output #3279
@@ -178,8 +178,11 @@ Feature: Plan CLI coverage round 2 – remaining uncovered lines
|
||||
And a mocked checkpoint service for r2cov rollback that succeeds
|
||||
When I invoke r2cov plan rollback with --yes
|
||||
Then the r2cov command should exit normally
|
||||
And the r2cov output should contain "Rollback Summary"
|
||||
And the r2cov output should contain "Changes Reverted"
|
||||
And the r2cov output should contain "Impact"
|
||||
And the r2cov output should contain "Post-Rollback State"
|
||||
And the r2cov output should contain "Rollback complete"
|
||||
And the r2cov output should contain "Restored files"
|
||||
|
||||
Scenario: Rollback plan succeeds in json format
|
||||
Given a r2cov CLI runner
|
||||
|
||||
@@ -3422,16 +3422,89 @@ def rollback_plan(
|
||||
if fmt != OutputFormat.RICH.value:
|
||||
console.print(format_output(data, fmt))
|
||||
else:
|
||||
# Rollback Summary panel
|
||||
label = getattr(result, "label", None) or ""
|
||||
label_line = f"\n[bold]Label:[/bold] {label}" if label else ""
|
||||
console.print(
|
||||
f"[green]Rollback complete.[/green]\n"
|
||||
f" Plan: {plan_id}\n"
|
||||
f" Checkpoint: {result.from_checkpoint_id}\n"
|
||||
f" Restored files: {result.restored_files_count}\n"
|
||||
f" Elapsed: {elapsed:.3f}s\n"
|
||||
f" Changed paths:"
|
||||
Panel(
|
||||
f"[bold]Plan:[/bold] {plan_id}\n"
|
||||
f"[bold]Checkpoint:[/bold] {result.from_checkpoint_id}"
|
||||
f"{label_line}\n"
|
||||
f"[bold]Files:[/bold] {result.restored_files_count} reverted",
|
||||
title="Rollback Summary",
|
||||
expand=False,
|
||||
)
|
||||
)
|
||||
for path in result.changed_paths:
|
||||
console.print(f" {path}")
|
||||
|
||||
# Changes Reverted table
|
||||
changes_table = Table(show_header=True, expand=False)
|
||||
changes_table.add_column("File", style="cyan")
|
||||
changes_table.add_column("Action", style="green")
|
||||
changes_reverted = getattr(result, "changes_reverted", None)
|
||||
if changes_reverted and isinstance(changes_reverted, list):
|
||||
for entry in changes_reverted:
|
||||
if isinstance(entry, dict):
|
||||
changes_table.add_row(
|
||||
str(entry.get("file", "")),
|
||||
str(entry.get("action", "restored")),
|
||||
)
|
||||
else:
|
||||
changes_table.add_row(str(entry), "restored")
|
||||
else:
|
||||
for path in result.changed_paths:
|
||||
changes_table.add_row(str(path), "restored")
|
||||
console.print(Panel(changes_table, title="Changes Reverted", expand=False))
|
||||
|
||||
# Impact panel
|
||||
child_plans_invalidated = getattr(result, "child_plans_invalidated", None)
|
||||
sandbox_state = getattr(result, "sandbox", None) or (
|
||||
f"restored to {result.from_checkpoint_id}"
|
||||
)
|
||||
decisions_after_cp = getattr(result, "decisions_after_cp", None)
|
||||
tool_calls_after_cp = getattr(result, "tool_calls_after_cp", None)
|
||||
impact_lines = []
|
||||
if child_plans_invalidated is not None:
|
||||
impact_lines.append(
|
||||
f"[bold]Child Plans Invalidated:[/bold] {child_plans_invalidated}"
|
||||
)
|
||||
impact_lines.append(f"[bold]Sandbox:[/bold] {sandbox_state}")
|
||||
if decisions_after_cp is not None:
|
||||
impact_lines.append(
|
||||
f"[bold]Decisions After CP:[/bold] {decisions_after_cp} discarded"
|
||||
)
|
||||
if tool_calls_after_cp is not None:
|
||||
impact_lines.append(
|
||||
f"[bold]Tool Calls After CP:[/bold] {tool_calls_after_cp} undone"
|
||||
)
|
||||
console.print(
|
||||
Panel(
|
||||
"\n".join(impact_lines),
|
||||
title="Impact",
|
||||
expand=False,
|
||||
)
|
||||
)
|
||||
|
||||
# Post-Rollback State panel
|
||||
phase = getattr(result, "phase", None) or "execute"
|
||||
state = getattr(result, "state", None) or "queued"
|
||||
checkpoints_remaining = getattr(result, "checkpoints_remaining", None)
|
||||
post_rollback_lines = [
|
||||
f"[bold]Phase:[/bold] {phase}",
|
||||
f"[bold]State:[/bold] {state}",
|
||||
]
|
||||
if checkpoints_remaining is not None:
|
||||
post_rollback_lines.append(
|
||||
f"[bold]Checkpoints Remaining:[/bold] {checkpoints_remaining}"
|
||||
)
|
||||
console.print(
|
||||
Panel(
|
||||
"\n".join(post_rollback_lines),
|
||||
title="Post-Rollback State",
|
||||
expand=False,
|
||||
)
|
||||
)
|
||||
|
||||
console.print("[green]\u2713 OK[/green] Rollback complete")
|
||||
|
||||
except BusinessRuleViolation as e:
|
||||
console.print(f"[red]Rollback blocked:[/red] {e.message}")
|
||||
|
||||
Reference in New Issue
Block a user