SIGN IN SIGN UP

fix(sdk): treat absent node.repoKeys as permissive in placement (#1625)

`RelaycastMessagingClient.nodeMapsRepo` used
`Boolean(node.repoKeys?.includes(repo))`, so any node whose roster row
lacked a `repo_keys` field (equivalent: no `repo:<key>` tags on the node)
failed every repo-scoped placement — the optional chain resolves to
`undefined`, and `Boolean(undefined)` is `false`. An absent field was
therefore indistinguishable from an explicit "deny every repo".

That was fine before per-node repo scoping had any publisher, because no
placement passed `repo`. Once callers started passing `repo` and the
check became load-bearing, deployments where nobody had opted into `repo:*`
tag advertisement lost every repo-scoped dispatch across the whole fleet
— placement observed `unmapped_repo` for every candidate.

Treat absent `repoKeys` as permissive:
- No `repoKeys` on the row → node has not opted in → placement allowed.
- `repoKeys: []` → operator explicitly published "this node hosts no
  repos" → placement still denied.
- `repoKeys: ['relay']` → per-repo scoping honoured as before.

This restores the pre-adoption behaviour for anyone who never published
tags, and keeps opt-in behaviour intact for anyone who does.

Two placement tests added:
- absent `repo_keys` field → placement succeeds
- present-but-empty `repo_keys: []` → placement fails `unmapped_repo`

The full `placement.test.mts` suite is 30/30 green (was 28/28).

Related: relay#1276 (`repo_keys` derived from `repo:` tags, 2026-07-15),
factory#412 (the fleet-wide dispatch outage this deblocks).

Co-authored-by: kjgbot <kjgbot@agentrelay.dev>
K
KJGBot committed
58a51e5d31f68c84653bb81dd73b1834471dd3c4
Parent: a8d2cab
Committed by GitHub <noreply@github.com> on 8/29/2026, 5:05:36 AM