From 24afb2b5be2830e58a7dd66334b8621a7f2938dc Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Sun, 26 Jul 2026 20:26:19 -0400 Subject: [PATCH 1/6] Pin the wiring, and correct a false claim in the operator alert Two findings, one from each reviewer, both about honesty of a different kind. The shepherd caught that my new degraded-alert text said the retained copy "will not age out on its own". It does. SweepRetainedDataDirectories reads a MISSING counter as 1, so a failed marker write costs exactly one extra service start -- the same reasoning we both used to establish that wrapping the write was safe. Telling an operator otherwise sends them to delete a multi-gigabyte directory for no reason. Same class of false operator-facing claim this round was about, just erring toward extra work instead of false comfort. DarlingSelfAlertEvaluator.cs:1191 now says it ages out one start later, and names the real signal: the countdown cannot advance while whatever blocked the write is still blocking it. The reviewer took my own mutation question and aimed it at the other new pins, which found that the HIGH fix itself was unpinned. Deleting `swapped = true`, neutralising the catch filter, dropping the cancellation guard, or deleting the preflight call all left the entire suite GREEN -- the logic tests pass because the logic is right, and the gated E2E is a happy path that by construction never throws after the swap and never meets an occupied port. The defect that reached an arming gate had no test that would notice it coming back. Closed with source-parsing pins on the HostHeaderGuardTests idiom, which exists in this repo for exactly this reason (#1648 was also a wiring omission a logic test could not see): DarlingStoreUpgradeTests.cs:319 pins that the post-commit catch stays AHEAD of the general one and never reverts, :343 that the cancellation path keeps its !swapped guard, :358 that the preflight is actually invoked before pg_upgrade. Catch-clause order is the mutation most likely to happen by accident -- consolidating error handling looks harmless, the compiler says nothing, and the store-bricking path returns silently. All four mutations verified caught, then reverted. Also documented why TryStopAsync is safe in the post-commit handler (oldStarted is already false) so nobody re-derives it. Full suite 3359 passed, 0 failed, 0 warnings; gated upgrade E2E green end to end. Co-Authored-By: Claude Fable 5 --- Darling/Darling.Tests/Darling.Tests.csproj | 5 ++ .../Darling.Tests/DarlingSelfAlertTests.cs | 7 +- .../Darling.Tests/DarlingStoreUpgradeTests.cs | 78 +++++++++++++++++++ .../DarlingSelfAlertEvaluator.cs | 8 +- .../DarlingStoreUpgrade.cs | 3 + 5 files changed, 99 insertions(+), 2 deletions(-) diff --git a/Darling/Darling.Tests/Darling.Tests.csproj b/Darling/Darling.Tests/Darling.Tests.csproj index c7a9252a87..d96fe3bed7 100644 --- a/Darling/Darling.Tests/Darling.Tests.csproj +++ b/Darling/Darling.Tests/Darling.Tests.csproj @@ -46,6 +46,11 @@ never sees them). HostHeaderGuardTests parses them to pin that the #1648 DNS-rebinding middleware is installed FIRST and in BOTH bind modes: the defect was a WIRING omission, not a logic bug, so the pure decision test alone would have passed on the broken build. --> + +