Severity: high (architecture) · canonical: packages/types/src/fleet-wire.ts; mirrors: relay crates/broker/src/fleet_wire.rs + crates/broker/src/relaycast/wire.rs, relaycast-cloud fleet/wire.ts
The node wire protocol is declared in five places today:
| Location |
Role |
Kept in sync by |
relaycast/packages/types/src/fleet-wire.ts |
canonical Zod |
— |
relaycast-cloud/.../fleet/wire.ts |
outbound TS superset |
implicit compile check (derives engine type from port signature) ✅ |
relay/crates/broker/src/fleet_wire.rs |
full Rust mirror |
manual + two independent fixture dirs ⚠️ |
relay/crates/broker/src/relaycast/wire.rs |
second contract: deliver-payload event shapes mirroring @relaycast/types events |
manual + packages/contracts fixtures ⚠️ |
relay/packages/harness-driver/src/protocol.ts |
harness↔broker plane |
manual ⚠️ |
The Rust mirror is synced only by two independent fixture directories in two repos (relay/crates/broker/tests/fixtures/fleet-wire/ vs relaycast/packages/types/fixtures/fleet-wire/), each validated by its own suite — nothing forces the two sets to match. This has already produced real drift:
context.update exists on the TS side only — the engine sends it to fleet_ws nodes (nodeContext.ts:33) and the broker WARN-drops every frame (relay issue filed). The Rust fixture set deliberately omits context.update.json, so both suites pass.
- Fixture rot — the two repos'
deliver.json payloads differ ({type,data} vs {channel,text,sender,…}); the engine's actual buildDeliverPayload (deliveryWire.ts:19-21) matches Rust, so the TS fixture is stale.
Recommendation: make fleet-wire.ts the single source and generate fleet_wire.rs (and one shared fixture corpus consumed by both test suites) via codegen (Zod → JSON Schema → typify/quicktype), checked in CI. This structurally prevents "a frame type exists on one side only." The engine↔cloud compile-checked derivation already proves the value of an enforced contract.
Found during a multi-agent cross-repo architecture review of the relay tool/protocol.
Severity: high (architecture) · canonical:
packages/types/src/fleet-wire.ts; mirrors: relaycrates/broker/src/fleet_wire.rs+crates/broker/src/relaycast/wire.rs, relaycast-cloudfleet/wire.tsThe node wire protocol is declared in five places today:
relaycast/packages/types/src/fleet-wire.tsrelaycast-cloud/.../fleet/wire.tsrelay/crates/broker/src/fleet_wire.rsrelay/crates/broker/src/relaycast/wire.rs@relaycast/typeseventspackages/contractsfixturesrelay/packages/harness-driver/src/protocol.tsThe Rust mirror is synced only by two independent fixture directories in two repos (
relay/crates/broker/tests/fixtures/fleet-wire/vsrelaycast/packages/types/fixtures/fleet-wire/), each validated by its own suite — nothing forces the two sets to match. This has already produced real drift:context.updateexists on the TS side only — the engine sends it tofleet_wsnodes (nodeContext.ts:33) and the broker WARN-drops every frame (relay issue filed). The Rust fixture set deliberately omitscontext.update.json, so both suites pass.deliver.jsonpayloads differ ({type,data}vs{channel,text,sender,…}); the engine's actualbuildDeliverPayload(deliveryWire.ts:19-21) matches Rust, so the TS fixture is stale.Recommendation: make
fleet-wire.tsthe single source and generatefleet_wire.rs(and one shared fixture corpus consumed by both test suites) via codegen (Zod → JSON Schema →typify/quicktype), checked in CI. This structurally prevents "a frame type exists on one side only." The engine↔cloud compile-checked derivation already proves the value of an enforced contract.Found during a multi-agent cross-repo architecture review of the relay tool/protocol.