CB-589: catalogue that weighted placement is not cheapest-first

Records the two traps: a maxLoad'd profile freezes its score and can
lose the next pick after a slot frees, and the weight-100 workaround
expresses a preference order through a ratio knob, so a future profile
added at a higher weight silently outranks the free box.
Dai Ha
2026-08-16 18:27:25 +02:00
parent e1106b3e8e
commit 113859d1c2
+29
@@ -1470,6 +1470,35 @@ callers were ever affected.
---
## `weighted` placement is not "cheapest first"
**What.** `placement: weighted` is smooth weighted round-robin. It spreads unqualified spawns across
**every** profile that has a free slot, in weight ratio. It has no concept of cost. So `local: 10`
against `terra: 2` and `sonnet: 1` does not mean "use local, overflow to paid" — it means roughly a
quarter of spawns go to a paid profile **while the free box still has a free slot**.
**On.** `placement: weighted` in `bridged.yaml`, with a `weight:` per profile. `weight: 0` excludes a
profile from automatic placement entirely; an explicit `bridge_spawn{profile:...}` bypasses placement
either way.
**Why.** The operator's rule is cheapest-first: keep the free boxes busy and pay only for genuine
overflow. No shipped policy expresses that. `FixedPlacementPolicy` ignores `maxLoad` and throws
instead of overflowing; `RoundRobinPlacementPolicy` has no cost notion. **CB-589** tracks a real
cost-first policy. Until then the workaround is to make the ratio *decisive* rather than
proportional — on this host `local.weight` is **100** against paid weights of about 1, so the free
box wins every pick it is eligible for.
**Gotcha, two of them.** First, the running score map lives for the daemon's whole life. While a
profile sits at `maxLoad` it is filtered out and its score **freezes**, so paid profiles keep
accumulating against it; when the free slot opens the profile returns with a stale score and can
*lose* the next pick — a paid spawn while the free box is idle. Second, and worse for the next
person: the workaround expresses a **preference order** through a **ratio** knob. Add a profile at
weight 150 later and it silently outranks the free box, with nothing to warn you. `bridged.yaml` is
gitignored, so a fresh host starts without this workaround and quietly pays — the reasoning is
written into `bridged.example.yaml` next to the key for exactly that reason.
---
## Which inherited credentials a member may keep
**What.** A member's pane runs a login shell, which re-sources the operator's secret store and