Skip to content

Report unbounded node load as unmeasured - #1445

Open
kjgbot wants to merge 3 commits into
mainfrom
agent/report-unbounded-node-load
Open

Report unbounded node load as unmeasured#1445
kjgbot wants to merge 3 commits into
mainfrom
agent/report-unbounded-node-load

Conversation

@kjgbot

@kjgbot kjgbot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What changed

  • represent broker heartbeat load as optional
  • omit load when max_agents == 0 instead of emitting a false 0
  • keep finite capacity utilization as active_agents / max_agents, clamped and validated in [0,1]
  • add wire and calculation coverage for a 25-agent unbounded node and a finite 3/4 node
  • verify the Relay SDK translates Relaycast load: null into an absent optional field, so agent-relay fleet nodes cannot render unknown utilization as zero

Root cause

The broker already measured active_agents from the live worker map and read an optional finite capacity from AGENT_RELAY_NODE_MAX_AGENTS. Runtime state intentionally normalized an absent capacity to max_agents: 0 (unlimited), but FleetLoadSnapshot::heartbeat then substituted 0.0 for the undefined ratio. That made “not measured” indistinguishable from “measured idle” all the way through the fleet roster.

load now means only managed-agent capacity utilization. It is numeric in [0,1] when a finite positive maximum exists and absent for an unlimited node. It does not represent CPU, memory, queue depth, or dispatch latency.

Compatibility and deployment order

Companion Relaycast PR: AgentWorkforce/relaycast#307

Relaycast must land and deploy first so the server accepts omitted/null load and persists it honestly. This PR must not be deployed independently before that compatibility layer is live.

Validation

  • broker heartbeat calculation test passed
  • broker fleet-wire heartbeat tests passed (finite, absent, negative, non-finite, and >1 cases)
  • Rust formatting check passed
  • Relay SDK messaging test passed (20 tests)
  • Relay SDK TypeScript typecheck passed

No deployment or merge is included.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cda1d4f0-c3c3-4deb-9821-ddd45aaca456

📥 Commits

Reviewing files that changed from the base of the PR and between 7cc7dff and b044376.

📒 Files selected for processing (1)
  • crates/broker/src/fleet_wire.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/broker/src/fleet_wire.rs

📝 Walkthrough

Walkthrough

Fleet heartbeat load is now optional. Zero-capacity nodes omit load, while bounded nodes report validated utilization from 0.0 through 1.0. Broker and SDK tests cover serialization, validation, calculation, and normalization.

Changes

Fleet heartbeat load reporting

Layer / File(s) Summary
Optional heartbeat load contract
crates/broker/src/fleet_wire.rs
NodeHeartbeat.load now uses Option<f64>. Absent and null values decode as None, and None is omitted during serialization. Present values must be finite and within 0.0..=1.0. Tests cover valid, invalid, boundary, and absent values.
Capacity-based load calculation
crates/broker/src/node_control.rs, packages/sdk/src/__tests__/messaging.test.ts, CHANGELOG.md
Zero-capacity nodes produce no load. Bounded nodes retain measured utilization. Broker and SDK tests cover the updated behavior, and the changelog records it.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: willwashburn, khaliqgant

Poem

A rabbit checks the heartbeat line,
Bounded loads stay in range.
Zero capacity sends no load,
Tests confirm the wire-level change.
Hop, hop—the fields remain alive!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: reporting unbounded node load as unmeasured.
Description check ✅ Passed The description explains the change, root cause, compatibility order, validation, and deployment scope, although it does not use the exact template headings.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/report-unbounded-node-load

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
crates/broker/src/fleet_wire.rs (2)

171-179: 🗄️ Data Integrity & Integration | 🔵 Trivial

Keep the Relaycast rollout prerequisite in the release gate.

This change omits load when max_agents == 0. Release the broker only after Relaycast PR #307 is deployed and accepts omitted or null load values. Otherwise, unbounded-node heartbeats can fail at the downstream wire boundary.

The PR objective states that Relaycast PR #307 must be deployed first.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/broker/src/fleet_wire.rs` around lines 171 - 179, Preserve the
Relaycast rollout prerequisite in the release gate: do not release this broker
change until Relaycast PR `#307` is deployed and its downstream wire handling
accepts omitted or null load values. Ensure the release checklist or gating
configuration explicitly records this dependency alongside the fleet-wire load
change.

840-861: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add broker-side decode coverage for unreported load.

node_heartbeat_omits_unreported_load checks only serialization from load: None. Add cases that deserialize a heartbeat with no load field and with "load": null. The SDK test in packages/sdk/src/__tests__/messaging.test.ts Line 488 covers null normalization, but this Rust wire test does not protect the broker-side deserialization contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/broker/src/fleet_wire.rs` around lines 840 - 861, Extend
node_heartbeat_omits_unreported_load to deserialize heartbeat payloads both
without a load field and with "load": null, asserting each produces load: None
while preserving the existing active_agents and max_agents expectations. Use the
existing BrokerToRelaycast/NodeHeartbeat serde path and keep the current
serialization assertions intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/broker/src/fleet_wire.rs`:
- Around line 171-179: Preserve the Relaycast rollout prerequisite in the
release gate: do not release this broker change until Relaycast PR `#307` is
deployed and its downstream wire handling accepts omitted or null load values.
Ensure the release checklist or gating configuration explicitly records this
dependency alongside the fleet-wire load change.
- Around line 840-861: Extend node_heartbeat_omits_unreported_load to
deserialize heartbeat payloads both without a load field and with "load": null,
asserting each produces load: None while preserving the existing active_agents
and max_agents expectations. Use the existing BrokerToRelaycast/NodeHeartbeat
serde path and keep the current serialization assertions intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 990e3ed5-ee0b-4e12-bf2f-448a96c7e0d8

📥 Commits

Reviewing files that changed from the base of the PR and between 7816e37 and af7d911.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • crates/broker/src/fleet_wire.rs
  • crates/broker/src/node_control.rs
  • packages/sdk/src/__tests__/messaging.test.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

Re-trigger cubic

…ploy-order dependency

Extends node_heartbeat_omits_unreported_load with round-trip decode
assertions for a heartbeat with load absent entirely and one with an
explicit `"load": null`, both of which must decode to `load: None`.
Previously only the serialize-side (Rust -> JSON) was covered.

Also records the Relaycast #307 deploy-order dependency inline in the
NodeHeartbeat field doc, not just the PR description, so it survives
merge.

Addresses CodeRabbit nitpicks on PR #1445.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
crates/broker/src/fleet_wire.rs (1)

744-762: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add tests for the inclusive load boundaries.

The test rejects 1.1, but it does not prove that 0.0 and 1.0 are accepted. Add successful encode/decode cases for both boundary values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/broker/src/fleet_wire.rs` around lines 744 - 762, Add successful
encode/decode coverage in the heartbeat validation tests around the existing
over-capacity case for load values 0.0 and 1.0. Use valid heartbeat payloads and
assert both boundary values deserialize successfully through BrokerToRelaycast,
while preserving the existing rejection assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/broker/src/fleet_wire.rs`:
- Around line 744-762: Add successful encode/decode coverage in the heartbeat
validation tests around the existing over-capacity case for load values 0.0 and
1.0. Use valid heartbeat payloads and assert both boundary values deserialize
successfully through BrokerToRelaycast, while preserving the existing rejection
assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d29d1f8-22ef-4d49-9d25-1e0baf4cc5d9

📥 Commits

Reviewing files that changed from the base of the PR and between af7d911 and 7cc7dff.

📒 Files selected for processing (1)
  • crates/broker/src/fleet_wire.rs

node_heartbeat_rejects_invalid_loads only proved 1.1 and -0.1 are
rejected; it never proved the inclusive boundaries 0.0 and 1.0
validate and decode successfully. Adds both to the existing test.

Addresses a CodeRabbit nitpick from the PR #1445 re-review.
@khaliqgant

Copy link
Copy Markdown
Member

Addressed CodeRabbit's nitpicks from both review passes:

  1. "Keep the Relaycast rollout prerequisite in the release gate" (initial review, fleet_wire.rs:171-179) — recorded the relaycast#307 deploy-order dependency directly on the NodeHeartbeat::load field doc comment, not just in this PR's description, so it survives merge for future readers. Fixed in 7cc7dffb3.

  2. "Add broker-side decode coverage for unreported load" (initial review, fleet_wire.rs:840-861) — node_heartbeat_omits_unreported_load only covered the serialize direction. Extended it with two decode-side cases: a heartbeat JSON payload with load absent entirely, and one with an explicit "load": null, both asserting NodeHeartbeat.load == None. Fixed in 7cc7dffb3.

  3. "Add tests for the inclusive load boundaries" (re-review after fix Add comprehensive architecture and design documentation #2, fleet_wire.rs:744-762) — node_heartbeat_rejects_invalid_loads proved 1.1 and -0.1 are rejected but never proved 0.0/1.0 are accepted. Added validate + decode assertions for both boundary values. Fixed in b044376b1.

Validation for all three: cargo test -p agent-relay-broker fleet_wire (12/12 passing) and cargo fmt -p agent-relay-broker -- --check (clean) after each commit; full CI is green on the current head (b044376b1).

Cubic reported no issues across both passes. No unresolved review feedback remains. Leaving open for human review/merge per policy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants