fix(central-ui): Flow Debugger prediction overlay matches by kind and title (arch-review F10)
Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
This commit is contained in:
@@ -410,11 +410,15 @@ public partial class FlowGraphView : ComponentBase
|
||||
|
||||
if (hasPredicted)
|
||||
{
|
||||
// Overlay: match predicted nodes to real steps by kind, in order; the leftovers are ghosts.
|
||||
// Overlay: match predicted nodes to real steps by (kind, title) first, falling back to kind
|
||||
// alone; the leftovers are ghosts. Kind-only matching pairs steps to predicted nodes in
|
||||
// declaration order, which mismatches a method with multiple same-kind calls when only some
|
||||
// of them actually ran (arch-review F10).
|
||||
var unmatched = predicted!.Nodes.ToList();
|
||||
foreach (var s in graph.Steps)
|
||||
{
|
||||
var m = unmatched.FirstOrDefault(p => p.Kind == s.Kind);
|
||||
var m = unmatched.FirstOrDefault(p => p.Kind == s.Kind && string.Equals(p.Title, s.Title, StringComparison.OrdinalIgnoreCase))
|
||||
?? unmatched.FirstOrDefault(p => p.Kind == s.Kind);
|
||||
if (m != null)
|
||||
{
|
||||
unmatched.Remove(m);
|
||||
|
||||
@@ -193,6 +193,30 @@ public class FlowGraphViewTests : BunitContext
|
||||
Assert.True(int.Parse(ghost.GetAttribute("data-column")!) > realMax);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Overlay_TwoPredictedRouteCalls_RealSecondCallMatchesByTitle_FirstIsTheGhost()
|
||||
{
|
||||
// The run only ever made the second of two predicted route calls (a branch skipped the first).
|
||||
// Matching by kind alone would pair the real "B.Y" step with the first predicted node ("A.X")
|
||||
// and leave "B.Y" as the ghost — wrong: "A.X" is the one that never ran.
|
||||
var step = new FlowStep(Guid.NewGuid(), null, null, FlowStepKind.RouteCall, FlowLane.Central, "B.Y", null,
|
||||
T0, 5, FlowStepOutcome.Ok, null, null, null, null, null, null, "B.Y", null);
|
||||
var graph = new FlowGraph([step], [], false, false);
|
||||
var predicted = new PredictedFlow(
|
||||
[
|
||||
new("n1", FlowStepKind.RouteCall, FlowLane.Central, "A.X", false, null),
|
||||
new("n2", FlowStepKind.RouteCall, FlowLane.Central, "B.Y", false, null),
|
||||
], []);
|
||||
|
||||
var layout = FlowGraphView.ComputeLayout(graph, predicted);
|
||||
|
||||
var real = Assert.Single(layout.Nodes, n => n.Step != null);
|
||||
Assert.Equal("B.Y", real.Predicted?.Title);
|
||||
var ghost = Assert.Single(layout.Nodes, n => n.Ghost);
|
||||
Assert.Equal("p:n1", ghost.Key);
|
||||
Assert.Equal("A.X", ghost.Predicted?.Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_UnderGermanCulture_CoordinatesStayInvariant()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user