host: the system leg observes once at arming, not an hour later
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QCUCpfxbCyEAVQ2m51dH5
2 files changed,
+12
−0
internal/host/agent.go+7 −0internal/host/systemleg_test.go+5 −0
diff --git a/internal/host/agent.go b/internal/host/agent.go| index 9f509684f..4836f8f05 100644 |
| --- a/internal/host/agent.go |
| +++ b/internal/host/agent.go |
| @@ -1534,6 +1534,13 @@ func fastConvergeLoop(reg *registry.Registry, svc *activator.Service, sd *schedu |
| // in a loop of its own because the spread deadline needs a seconds |
| // cadence to run down on, and this is the loop that already has one. |
| d.systemLeg = newSystemLeg(store, pub, os.Getenv, dd, optDir) |
| + // One observe at arming, on restartSeed's precedent: the leg below only |
| + // re-observes on a serial move or at its hourly floor, so a box that |
| + // (re)starts under an already-promoted pointer would otherwise sit on the |
| + // old build for up to an hour with nobody to bump the serial. observe |
| + // handles "no pointer" itself, which is every deployment before its first |
| + // `carlos system update`. |
| + d.systemLeg.observe(ctx) |
| log.Printf("agent: fast converge loop armed (2s + jitter: serial poll + canary/* + unstaged routes + system pointer)") |
| for { |
| time.Sleep(fastTickEvery + rand.N(time.Second)) |
diff --git a/internal/host/systemleg_test.go b/internal/host/systemleg_test.go| index 437e74f3b..a8bc4bb56 100644 |
| --- a/internal/host/systemleg_test.go |
| +++ b/internal/host/systemleg_test.go |
| @@ -101,6 +101,11 @@ func TestSystemLegFetchesVerifiesAndRequestsAfterTheSpread(t *testing.T) { |
| body := []byte("ELF v2") |
| f.promote("v2", body, 10*time.Minute) |
| f.leg.observe(context.Background()) |
| + // One observe with a pointer present arms the pending update — this is |
| + // what fastConvergeLoop's observe-at-arming relies on. |
| + if f.leg.pending == nil || f.leg.pending.version != "v2" { |
| + t.Fatalf("observe armed pending = %+v, want v2", f.leg.pending) |
| + } |
| if _, err := f.marker(); err == nil { |
| t.Fatal("requested before the spread elapsed") |
| } |