carlos / platform Public

host: make status.SnapshotPeriod actually govern the heartbeat it names

The const fed statusTick's BuildFleet argument and the two new readers, but
statusLoop's own sleep still hardcoded 5*time.Minute — so changing
SnapshotPeriod would have moved every "is this box dark?" judgement while the
boxes kept reporting on the old beat, which is the exact drift the const was
introduced to close. The tick now sleeps SnapshotPeriod + jitter, and the
armed log line quotes the period rather than restating "5min" from memory.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 0b775cd35cf18cbe24b12ad1010950915f7466cd parent 4137c3e
1 file changed, +9 −4
  • internal/host/agent.go +9 −4
diff --git a/internal/host/agent.go b/internal/host/agent.go
index 09f968a6a..b36dbd05f 100644
--- a/internal/host/agent.go
+++ b/internal/host/agent.go
@@ -597,7 +597,7 @@ func statusLoop(reg *registry.Registry) {
// by accident (or on purpose) and end up with the agent writing status
// to a bucket the edge/console never look at — this line is the one
// place an operator can confirm which bucket actually won.
- log.Printf("agent: status loop armed (5min + jitter), publishing to bucket %s", bucket)
+ log.Printf("agent: status loop armed (%s + jitter), publishing to bucket %s", status.SnapshotPeriod, bucket)
// canaryStore/canaryPub resolve the release deployment config
// countExpiredCanaries needs to answer §5's "how many canaries on this
@@ -614,13 +614,18 @@ func statusLoop(reg *registry.Registry) {
canaryStore, _ := openDeployStore(ctx)
canaryPub, _ := release.ParsePublicKey(os.Getenv("CARLOS_RELEASE_PUBKEY"), "CARLOS_RELEASE_PUBKEY")
+ // status.SnapshotPeriod IS this cadence — the const is named for the tick
+ // below, and every reader that judges a box stale (the published boxes
+ // table, the console's private host detail, `carlos status -live`) measures
+ // against it, so changing it here must move them together rather than
+ // leaving them judging a heartbeat that arrives on a different beat.
// Jittered on the same shape as adoptLoop's delay: every box on the same
- // 5-minute cadence would all hit the lease and the bucket in the same
- // second otherwise.
+ // cadence would all hit the lease and the bucket in the same second
+ // otherwise.
delay := time.Minute
for {
time.Sleep(delay)
- delay = 5*time.Minute + rand.N(time.Minute)
+ delay = status.SnapshotPeriod + rand.N(time.Minute)
// Routes are listed here (not left to statusTick's own reg.List())
// because the Listening probe needs to know which sockets are