diff --git a/fleetd/src/main/java/dev/ltms/fleet/config/ConfigRef.java b/fleetd/src/main/java/dev/ltms/fleet/config/ConfigRef.java index 7b490fb..fcd38c6 100644 --- a/fleetd/src/main/java/dev/ltms/fleet/config/ConfigRef.java +++ b/fleetd/src/main/java/dev/ltms/fleet/config/ConfigRef.java @@ -45,8 +45,12 @@ import java.util.function.Supplier; * {@link #changedDeferredKeys}), {@code primary:} (fleetd #326 — {@code Fleetd.java:506, 519, * 520} read {@code cfg.primary()} only off the startup snapshot to build {@code * PrimaryRegistry} and size {@code ReplyPushLoop}'s reminder cap/backoff, and neither is - * rebuilt on reload; a lead whose pinned terminal changed under a running daemon stays - * unresolved as primary until a restart), {@code configReload:} (fleetd #326 — {@code + * rebuilt on reload. Say the consequence exactly: {@code primary.terminal} is DEPRECATED + * (CB-532, and {@code Fleetd.java:511} warns about it at startup) — a lead's identity comes + * from {@code leaders:}/{@code leadScan:}, so changing this pin does not demote or promote a + * lead that uses those. What a changed pin still does not take effect on until a restart is + * the fallback nudge destination the pin remains, the deprecated identity path for an operator + * who still relies on it, and {@code pushReminders}/{@code pushBackoffMs}), {@code configReload:} (fleetd #326 — {@code * Fleetd.java:679-680} read it only at startup to decide whether to build a {@code * ConfigWatcher} at all and with what interval; the watcher that would apply a later change is * itself built once, so a running watcher keeps polling on its original enabled flag and @@ -73,6 +77,24 @@ import java.util.function.Supplier; * listening. * * + *

The denominator, measured on 2026-09-04 (fleetd #326). {@code FleetConfig} has + * 22 top-level record components. Four of them are named nowhere in this file, and the reason + * differs per key, so do not read "absent" as "forgotten": + *

+ * The point of writing the count down: "not mentioned in this file" looks identical for a key that + * is correctly hot and for a key nobody triaged. Twice now — {@code worktreeGroup} (#323) and + * {@code primary}/{@code configReload} (#326) — the second kind hid among the first. + * *

A cold change refuses the whole reload. Not the hot half applied and the cold * half warned about: that would leave the running daemon in a state matching no file on disk, which * is the worst thing a reload can do to an operator debugging one. Refusing keeps the invariant that @@ -246,7 +268,9 @@ public final class ConfigRef implements Supplier { } // fleetd #326: Fleetd.java:506, 519, 520 read cfg.primary() only off the startup snapshot // (PrimaryRegistry's pinned terminal, ReplyPushLoop's reminder cap and backoff) — neither is - // rebuilt on reload, so a changed pin needs a restart before a lead resolves as primary again. + // rebuilt on reload, so a changed value needs a restart. Note what it does NOT mean: + // primary.terminal is deprecated (CB-532), identity comes from leaders:/leadScan:, so a lead + // using those is unaffected by this pin either way. See the class doc for the exact scope. if (!Objects.equals(old.primary(), fresh.primary())) { changed.add("primary"); }