diff --git a/src/DiffEngine.Tests/DisabledTests.cs b/src/DiffEngine.Tests/DisabledTests.cs
new file mode 100644
index 00000000..ed2f3382
--- /dev/null
+++ b/src/DiffEngine.Tests/DisabledTests.cs
@@ -0,0 +1,38 @@
+///
+/// was captured at type initialisation, so a build server or AI
+/// CLI reported after that - which is when a test host reports one, having only just loaded - left
+/// diff tools launching anyway.
+///
+[NotInParallel]
+public class DisabledTests
+{
+ [Test]
+ public async Task A_build_server_detected_after_first_use_still_disables()
+ {
+ // As the module initializer left it, and as any consumer that ever set it leaves it
+ DiffRunner.Disabled = false;
+
+ DiffRunner.ResetDisabled();
+ BuildServerDetector.Detected = true;
+
+ await Assert.That(DiffRunner.Disabled).IsTrue();
+ }
+
+ [Test]
+ public async Task Setting_it_pins_it()
+ {
+ DiffRunner.ResetDisabled();
+ BuildServerDetector.Detected = true;
+
+ DiffRunner.Disabled = false;
+
+ await Assert.That(DiffRunner.Disabled).IsFalse();
+ }
+
+ ///
+ /// Every other test in this assembly runs with it off, which the module initializer does once.
+ ///
+ [After(Test)]
+ public void Restore() =>
+ DiffRunner.Disabled = false;
+}
diff --git a/src/DiffEngine/DiffRunner.cs b/src/DiffEngine/DiffRunner.cs
index eb492457..cef9327e 100644
--- a/src/DiffEngine/DiffRunner.cs
+++ b/src/DiffEngine/DiffRunner.cs
@@ -6,7 +6,33 @@ namespace DiffEngine;
///
public static partial class DiffRunner
{
- public static bool Disabled { get; set; } = DisabledChecker.IsDisable();
+ ///
+ /// Whether launching a diff tool is turned off, for this process or for this async context.
+ ///
+ /// Read rather than captured, so that the overrides feeding it -
+ /// and , both of which a test host sets after it has
+ /// loaded - are honoured whenever they are set. Captured once at type initialisation, they
+ /// were inert the moment anything had touched this class, and an AsyncLocal override could
+ /// never have reached a value read into a static anyway.
+ ///
+ ///
+ /// Setting it pins it, and nothing is read from the environment after that.
+ ///
+ ///
+ public static bool Disabled
+ {
+ get => disabled ?? DisabledChecker.IsDisable();
+ set => disabled = value;
+ }
+
+ static bool? disabled;
+
+ ///
+ /// Forgets an explicit , so it is read from the environment again. For
+ /// tests, which is where anything sets it and then wants the detectors back.
+ ///
+ internal static void ResetDisabled() =>
+ disabled = null;
public static void MaxInstancesToLaunch(int value) =>
MaxInstance.SetForAppDomain(value);