Skip to content
Tracon

EvalRunDiff

Namespace Tracon · Assembly Tracon.Abstractions.dll

The case-by-case difference between two completed EvalRun records of the same suite.

public sealed record EvalRunDiff : IEquatable<EvalRunDiff>

objectEvalRunDiff

IEquatable<EvalRunDiff>

object.GetType(), object.ToString(), object.Equals(object?), object.Equals(object?, object?), object.ReferenceEquals(object?, object?), object.GetHashCode()

A single “how many broke” number is not enough to act on: the engineer on call wants to know which case broke. Every aligned case therefore lands in exactly one EvalCaseDiffKind bucket, and each entry carries both sides’ agent run identifier, so a regression is one click away from the two conversations that produced it.

Cases are aligned by EvalCaseResult.CaseId, and case content is not snapshotted per run. If a case’s EvalCase.Query is edited between the two runs while its identifier is kept, the two sides describe different questions and the diff silently compares them as one. Through the HTTP surface this cannot happen (PUT /api/evals/{name}/cases replaces cases and assigns fresh identifiers, so an edit shows up as a EvalCaseDiffKind.Removed plus an EvalCaseDiffKind.Added entry); it can only happen when a consumer calls IEvalStore.ReplaceCasesAsync directly and preserves identifiers. Nothing here detects that, and no guarantee is offered against it.

The counters are for the whole diff and do not shrink with paging; EvalRunDiff.Cases is the requested page.

public EvalRunDiff()

The number of cases present only in the candidate run.

public required int AddedCount { get; init; }

int

The run being compared against (the older, known-good side).

public required EvalRun Baseline { get; init; }

EvalRun

The run being judged.

public required EvalRun Candidate { get; init; }

EvalRun

The requested page of aligned cases, ordered so that the buckets an engineer looks for come first: EvalCaseDiffKind.Regressed, EvalCaseDiffKind.StillFailing, EvalCaseDiffKind.Added, EvalCaseDiffKind.Fixed, EvalCaseDiffKind.Removed, then EvalCaseDiffKind.Unchanged; within a bucket by case identifier.

public required IReadOnlyList<EvalCaseDiff> Cases { get; init; }

IReadOnlyList<EvalCaseDiff>

The number of cases that failed on the baseline and pass now.

public required int FixedCount { get; init; }

int

The number of cases that passed on the baseline and fail now.

public required int RegressedCount { get; init; }

int

The number of cases present only in the baseline run.

public required int RemovedCount { get; init; }

int

The number of cases that failed on both sides.

public required int StillFailingCount { get; init; }

int

The number of aligned cases across both runs, ignoring paging.

public required int TotalCases { get; init; }

int

The number of cases that passed on both sides.

public required int UnchangedCount { get; init; }

int

public override bool Equals(object? obj)

obj object?

bool

public bool Equals(EvalRunDiff? other)

other EvalRunDiff?

bool

public override int GetHashCode()

int

public override string ToString()

string

public static bool operator ==(EvalRunDiff? left, EvalRunDiff? right)

left EvalRunDiff?

right EvalRunDiff?

bool

public static bool operator !=(EvalRunDiff? left, EvalRunDiff? right)

left EvalRunDiff?

right EvalRunDiff?

bool