feat(sandbox): Placement trait with least-loaded default

Merged
BN
5d ago
+397-37

Stacked on #619.

Extracts ranking out of place() behind a Placement trait (crates/preloop-sandbox/src/placement.rs). The service keeps the hard-constraint filter and builds the candidate list; Placement::rank returns a ranked list and the service takes the first. LeastLoaded reproduces today's ordering and tie-breaks exactly. Selected by PRELOOP_SANDBOX_PLACEMENT (default least-loaded); an unknown value fails startup listing the valid names.

No proto change. Tests: LeastLoaded ordering/ties, name resolution, and a conformance test proving a custom placement in ServiceConfig is honoured.

Checked: cargo clippy -p preloop-sandbox -p preloop-cli -p preloop-orchestrator --all-targets -D warnings, cargo test -p preloop-sandbox.


Summary by cubic

Introduces a Placement trait so the sandbox service's candidate ranking is configurable instead of hard-coded least-loaded.

  • The service keeps the hard-constraint filter (offline providers, capability gaps, slot caps); Placement::rank orders survivors and the service takes the first returned candidate.
  • LeastLoaded reproduces the old ordering and tie-breaks exactly and remains the default.
  • PRELOOP_SANDBOX_PLACEMENT selects a built-in strategy; an unknown name fails startup listing the valid ones.
  • Custom placements plug in via ServiceConfig::placement.
  • Includes a conformance test proving a configured placement overrides the default ranking; docs updated.