Persist unreported fleet node load honestly

Merged
KJ
2mo ago
+184-1

What changed

  • accept absent or null node.heartbeat.load and constrain measured values to [0,1]
  • persist an explicit load_reported bit for nodes and providers via migration 0034
  • return load: null when a node-wide load is not fully measured
  • preserve max_agents: 0 as unlimited across provider aggregates
  • rank unknown-load nodes by active agent count rather than treating them as measured idle
  • update TypeScript, Python, Rust, and Swift SDK contracts and heartbeat producers

Why

Unbounded providers use max_agents: 0. Existing heartbeats and persistence converted the undefined utilization ratio into load: 0, so a node with 25 active agents appeared identical to one with 4 and consumers rendered both as confidently idle.

load now has one definition: managed-agent capacity utilization (active_agents / max_agents), bounded to [0,1]. CPU, memory, queue depth, and dispatch latency are separate metrics. When no finite denominator exists—or any constituent provider is unmeasured—the aggregate load is explicitly unavailable.

The migration also keeps old unbounded-provider load: 0 heartbeats unreported during a rolling upgrade, so legacy senders cannot revive the false idle state.

Impact

GET /v1/nodes now returns load: null when utilization is unavailable. SDK consumers must handle the nullable field. Finite-capacity nodes continue returning a numeric ratio.

Companion Relay broker PR: https://github.com/AgentWorkforce/relay/pull/1445

Validation

  • 101 focused engine, fleet-wire, and TypeScript SDK tests passed
  • TypeScript typechecks passed for engine, types, and SDK packages
  • Python node SDK: 17 tests passed
  • Rust SDK: 42 tests passed
  • migration 0034 backfill exercised against finite, unbounded, mixed-provider, and direct-node fixtures
  • Swift implementation sources compiled; Swift tests could not run on this host because the installed toolchain lacks XCTest