diff --git a/OpenNest.Engine/AccumulatingProgress.cs b/OpenNest.Engine/AccumulatingProgress.cs
new file mode 100644
index 0000000..7b84803
--- /dev/null
+++ b/OpenNest.Engine/AccumulatingProgress.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+
+namespace OpenNest
+{
+ ///
+ /// Wraps an IProgress to prepend previously placed parts to each report,
+ /// so the UI shows the full picture during incremental fills.
+ ///
+ internal class AccumulatingProgress : IProgress
+ {
+ private readonly IProgress inner;
+ private readonly List previousParts;
+
+ public AccumulatingProgress(IProgress inner, List previousParts)
+ {
+ this.inner = inner;
+ this.previousParts = previousParts;
+ }
+
+ public void Report(NestProgress value)
+ {
+ if (value.BestParts != null && previousParts.Count > 0)
+ {
+ var combined = new List(previousParts.Count + value.BestParts.Count);
+ combined.AddRange(previousParts);
+ combined.AddRange(value.BestParts);
+ value.BestParts = combined;
+ value.BestPartCount = combined.Count;
+ }
+
+ inner.Report(value);
+ }
+ }
+}
diff --git a/OpenNest.Tests/AccumulatingProgressTests.cs b/OpenNest.Tests/AccumulatingProgressTests.cs
new file mode 100644
index 0000000..2df42c5
--- /dev/null
+++ b/OpenNest.Tests/AccumulatingProgressTests.cs
@@ -0,0 +1,51 @@
+namespace OpenNest.Tests;
+
+public class AccumulatingProgressTests
+{
+ private class CapturingProgress : IProgress
+ {
+ public NestProgress Last { get; private set; }
+ public void Report(NestProgress value) => Last = value;
+ }
+
+ [Fact]
+ public void Report_PrependsPreviousParts()
+ {
+ var inner = new CapturingProgress();
+ var previous = new List { TestHelpers.MakePartAt(0, 0, 10) };
+ var accumulating = new AccumulatingProgress(inner, previous);
+
+ var newParts = new List { TestHelpers.MakePartAt(20, 0, 10) };
+ accumulating.Report(new NestProgress { BestParts = newParts, BestPartCount = 1 });
+
+ Assert.NotNull(inner.Last);
+ Assert.Equal(2, inner.Last.BestParts.Count);
+ Assert.Equal(2, inner.Last.BestPartCount);
+ }
+
+ [Fact]
+ public void Report_NoPreviousParts_PassesThrough()
+ {
+ var inner = new CapturingProgress();
+ var accumulating = new AccumulatingProgress(inner, new List());
+
+ var newParts = new List { TestHelpers.MakePartAt(0, 0, 10) };
+ accumulating.Report(new NestProgress { BestParts = newParts, BestPartCount = 1 });
+
+ Assert.NotNull(inner.Last);
+ Assert.Single(inner.Last.BestParts);
+ }
+
+ [Fact]
+ public void Report_NullBestParts_PassesThrough()
+ {
+ var inner = new CapturingProgress();
+ var previous = new List { TestHelpers.MakePartAt(0, 0, 10) };
+ var accumulating = new AccumulatingProgress(inner, previous);
+
+ accumulating.Report(new NestProgress { BestParts = null });
+
+ Assert.NotNull(inner.Last);
+ Assert.Null(inner.Last.BestParts);
+ }
+}