diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 71800322..ac3ba51c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -98,11 +98,16 @@ jobs:
# Keep current repo LAST. Do not duplicate SAM_UI earlier in the list.
$buildOrder = @(
'SAM'
+ 'SAM_Mollier'
'SAM_Systems'
'SAM_Windows'
- 'SAM_Mollier'
'SAM_gbXML'
'SAM_SolarCalculator'
+ # Must precede SAM_Tas: SAM_Tas\benchmark\SAM.Analytical.Tas.Benchmark references
+ # SAM_Validation\build\SAM.Analytical.Benchmark.dll by HintPath, and without it it fails
+ # CS0234. Same slot as BuildAlls_v4.csproj uses locally. Needs only SAM and SAM_Mollier,
+ # both already above.
+ 'SAM_Validation'
'SAM_Tas'
'SAM_Excel'
'SAM_GEM'
@@ -123,7 +128,18 @@ jobs:
# Current sow branch: base_ref on PR events, ref_name on push events.
$sowRef = if ($baseRef -match '^sow/') { $baseRef } elseif ($refName -match '^sow/') { $refName } else { '' }
if ($sowRef -and $sowRef -ne $headRef) { $candidates += $sowRef }
- $candidates += 'sow/2026-Q2'
+ # Canonical quarter branch (strip suffixes like -update-optimization): e.g. sow/2026-Q3.
+ # On push events base_ref is empty and ref_name may be a feature branch off a sow branch,
+ # so without this the dep clone falls back to master and misses in-quarter API changes.
+ $canonical = ''
+ foreach ($cref in @($headRef, $baseRef, $refName)) {
+ if ($cref -match 'sow/(\d{4})-Q(\d)') { $canonical = "sow/$($Matches[1])-Q$($Matches[2])"; break }
+ }
+ if ($canonical -and $candidates -notcontains $canonical) { $candidates += $canonical }
+ # Hard fallbacks to the active quarter branches (in priority order).
+ foreach ($fb in @('sow/2026-Q3', 'sow/2026-Q2')) {
+ if ($candidates -notcontains $fb) { $candidates += $fb }
+ }
# Use the auth-token form so private deps (e.g. SAM_Solver) don't prompt
$url = if ($token) { "https://$token@github.com/$org/$r.git" } else { "https://github.com/$org/$r.git" }
$cloned = $false
@@ -170,11 +186,16 @@ jobs:
# Keep current repo LAST. SAM_Solver must be built before SAM_UI.
$buildOrder = @(
'SAM'
+ 'SAM_Mollier'
'SAM_Systems'
'SAM_Windows'
- 'SAM_Mollier'
'SAM_gbXML'
'SAM_SolarCalculator'
+ # Must precede SAM_Tas: SAM_Tas\benchmark\SAM.Analytical.Tas.Benchmark references
+ # SAM_Validation\build\SAM.Analytical.Benchmark.dll by HintPath, and without it it fails
+ # CS0234. Same slot as BuildAlls_v4.csproj uses locally. Needs only SAM and SAM_Mollier,
+ # both already above.
+ 'SAM_Validation'
'SAM_Tas'
'SAM_Excel'
'SAM_GEM'
diff --git a/Application/SAM Analytical Mollier/SAM Analytical Mollier.csproj b/Application/SAM Analytical Mollier/SAM Analytical Mollier.csproj
index 6f3692a9..3bfcb556 100644
--- a/Application/SAM Analytical Mollier/SAM Analytical Mollier.csproj
+++ b/Application/SAM Analytical Mollier/SAM Analytical Mollier.csproj
@@ -11,7 +11,7 @@
false
true
true
- Debug;Release;net48-windows
+ Debug;Release
SAM.ico
diff --git a/Application/SAM Analytical/SAM Analytical.csproj b/Application/SAM Analytical/SAM Analytical.csproj
index 4f5fa489..9d3684f8 100644
--- a/Application/SAM Analytical/SAM Analytical.csproj
+++ b/Application/SAM Analytical/SAM Analytical.csproj
@@ -11,7 +11,7 @@
false
true
true
- Debug;Release;net48-windows
+ Debug;Release
SAM.ico
@@ -50,11 +50,9 @@
..\..\..\SAM\build\SAM.Core.dll
-
..\..\..\SAM\build\SAM.Geometry.dll
-
@@ -153,7 +151,7 @@
2.27.0
-
+
1.9.7
diff --git a/Application/SAM Geometry/SAM Geometry.csproj b/Application/SAM Geometry/SAM Geometry.csproj
index c9984bab..dae119eb 100644
--- a/Application/SAM Geometry/SAM Geometry.csproj
+++ b/Application/SAM Geometry/SAM Geometry.csproj
@@ -9,7 +9,7 @@
false
true
true
- Debug;Release;net48-windows
+ Debug;Release
..\..\build\
@@ -24,8 +24,6 @@
-
-
diff --git a/Application/SAM Weather/SAM Weather.csproj b/Application/SAM Weather/SAM Weather.csproj
index 545f4072..f5ff0ba4 100644
--- a/Application/SAM Weather/SAM Weather.csproj
+++ b/Application/SAM Weather/SAM Weather.csproj
@@ -10,7 +10,7 @@
false
true
true
- Debug;Release;net48-windows
+ Debug;Release
SAM.ico
@@ -22,8 +22,6 @@
..\..\..\SAM\build\SAM.Weather.dll
-
-
diff --git a/Directory.Build.props b/Directory.Build.props
index 509f4c68..39ed51d0 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -23,6 +23,15 @@
true
+
+
+ 2.6.0
+
+
+
+ ..\..\..\SAM\build\SAM.Architectural.dll
+
+
+
+ ..\..\..\SAM\build\SAM.Weather.dll
+
+
+
+ ..\..\..\SAM_Tas\build\SAM.Analytical.Tas.dll
+
+
+
+
+ ..\..\..\SAM_Systems\build\SAM.Analytical.Systems.dll
+
+
+ ..\..\..\SAM_Systems\build\SAM.Core.Systems.dll
+
+
+ ..\..\..\SAM_Tas\build\SAM.Analytical.Tas.TPD.dll
+
+
+ ..\..\..\SAM_Tas\build\SAM.Core.Tas.dll
+
+
+ ..\..\..\SAM_Tas\build\SAM.Analytical.Tas.TM59.dll
+
+
+
+ ..\..\..\SAM\build\SAM.Analytical.Reporting.dll
+
+
+ ..\..\..\SAM\build\SAM.Core.Reporting.dll
+
+
+ ..\..\..\SAM\build\SAM.Core.Reporting.Pdf.dll
+
+
+ ..\..\..\SAM\build\SAM.Units.dll
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPF/SAM.Analytical.UI.WPF.Tests/SearchWindowConfirmTests.cs b/WPF/SAM.Analytical.UI.WPF.Tests/SearchWindowConfirmTests.cs
new file mode 100644
index 00000000..11c5fb54
--- /dev/null
+++ b/WPF/SAM.Analytical.UI.WPF.Tests/SearchWindowConfirmTests.cs
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+// Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Automation.Peers;
+using System.Windows.Automation.Provider;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Threading;
+using SAM.Core.UI.WPF;
+using Xunit;
+
+namespace SAM.Analytical.UI.WPF.Tests
+{
+ ///
+ /// - the "Select Construction" / "Select Filter" / ... picker - can be
+ /// confirmed. Before this it had an OK button with no Click handler and no IsDefault, and nothing wired
+ /// to double-click, so every ShowDialog() != true caller (Assign Construction, Assign Aperture
+ /// Construction, Assign Internal Condition, the Create Case controls, ...) could only ever be closed with
+ /// Cancel and the choice was never applied.
+ ///
+ /// Each test opens a real modal window and drives it from the dispatcher once it has rendered. A watchdog
+ /// closes the window if a confirm path is broken, so a regression fails the assertion instead of hanging
+ /// the run.
+ ///
+ ///
+ [Collection(WpfCollection.Name)]
+ public class SearchWindowConfirmTests
+ {
+ private sealed class Item
+ {
+ public Item(string name)
+ {
+ Name = name;
+ }
+
+ public string Name { get; }
+ }
+
+ private static SearchWindow Create(out List- items, SelectionMode selectionMode = SelectionMode.Single)
+ {
+ items = new List
- { new Item("Brick"), new Item("Concrete"), new Item("Timber") };
+
+ return new SearchWindow(items, x => (x as Item)?.Name) { SelectionMode = selectionMode };
+ }
+
+ private static T Field(object instance, string name) where T : class
+ {
+ FieldInfo fieldInfo = instance.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+
+ return fieldInfo?.GetValue(instance) as T;
+ }
+
+ private static ListBox ListBoxOf(SearchWindow window)
+ {
+ return Field(Field(window, "SearchControl_Main"), "ListBox_Main");
+ }
+
+ private static Button OKOf(SearchWindow window)
+ {
+ return Field