");
+ sb.AppendLine($"{label}
");
+ }
+ else
+ {
+ sb.AppendLine($"**{label}**");
+ }
+
+ sb.AppendLine();
+ sb.AppendLine("| Test | Suite | Duration |");
+ sb.AppendLine("| --- | --- | --- |");
+
+ var displayCount = Math.Min(entries.Count, MaxTestsPerGroup);
+ for (var i = 0; i < displayCount; i++)
+ {
+ var (suite, test, owner) = entries[i];
+ var sourcePart = BuildSourceLink(test, owner, serverUrl) is { } link ? $" {link}" : "";
+ sb.AppendLine($"| `{test.ClassName}.{test.DisplayName}`{sourcePart} | `{suite}` | {FormatDuration(test.DurationMs)} |");
+ }
+
+ if (entries.Count > MaxTestsPerGroup)
+ {
+ sb.AppendLine($"| *...and {entries.Count - MaxTestsPerGroup} more* | | |");
+ }
+
+ var commonError = entries
+ .Select(static e => e.Test.Exception?.Message)
+ .Where(static m => !string.IsNullOrWhiteSpace(m))
+ .GroupBy(static m => m)
+ .OrderByDescending(static g => g.Count())
+ .FirstOrDefault()
+ ?.Key;
+
+ if (commonError is not null)
+ {
+ sb.AppendLine();
+ sb.AppendLine("**Common error:**");
+ sb.AppendLine($"{WebUtility.HtmlEncode(Truncate(commonError, 1000))}");
+ }
+
+ if (collapsible)
+ {
+ sb.AppendLine();
+ sb.AppendLine(" ");
+ }
+
+ sb.AppendLine();
+ }
+ }
+
+ private static string ExceptionLabel(ReportTestResult test)
+ {
+ if (test.Status == "timedOut")
+ {
+ return "Timeout";
+ }
+
+ var type = test.Exception?.Type;
+ if (string.IsNullOrEmpty(type))
+ {
+ return "Unknown";
+ }
+
+ // Sidecars store the exception's FullName; the summary groups by short name,
+ // matching the per-suite GitHub summary.
+ var lastDot = type!.LastIndexOf('.');
+ return lastDot >= 0 ? type.Substring(lastDot + 1) : type;
+ }
+
+ private static string? BuildSourceLink(ReportTestResult test, ReportData owner, string? serverUrl)
+ {
+ if (string.IsNullOrEmpty(serverUrl)
+ || string.IsNullOrEmpty(owner.RepositorySlug)
+ || string.IsNullOrEmpty(owner.CommitSha)
+ || string.IsNullOrEmpty(test.SourceRelativePath)
+ || test.LineNumber is not { } line)
+ {
+ return null;
+ }
+
+ var fileName = Path.GetFileName(test.SourceRelativePath!);
+ return $"[{fileName}:{line}]({serverUrl!.TrimEnd('/')}/{owner.RepositorySlug}/blob/{owner.CommitSha}/{test.SourceRelativePath}#L{line})";
+ }
+
+ private static string Truncate(string value, int maxLength)
+ => value.Length <= maxLength ? value : value.Substring(0, maxLength) + "…";
+
+ internal static string FormatDuration(double milliseconds) => milliseconds switch
+ {
+ < 1 => "< 1ms",
+ < 1000 => $"{milliseconds:F0}ms",
+ < 60_000 => $"{milliseconds / 1000:F1}s",
+ < 3_600_000 => $"{(int)(milliseconds / 60_000)}m {(int)(milliseconds % 60_000 / 1000)}s",
+ _ => $"{(int)(milliseconds / 3_600_000)}h {(int)(milliseconds % 3_600_000 / 60_000)}m",
+ };
+}
diff --git a/TUnit.Engine/Reporters/Aggregation/AtomicFile.cs b/TUnit.Engine/Reporters/Aggregation/AtomicFile.cs
new file mode 100644
index 00000000000..fdeefb5d8ab
--- /dev/null
+++ b/TUnit.Engine/Reporters/Aggregation/AtomicFile.cs
@@ -0,0 +1,74 @@
+using System.IO;
+using System.Text;
+
+namespace TUnit.Engine.Reporters.Aggregation;
+
+///