Public: anyone can read this; the crew can change it.
Placement policy: owned capacity first, burst spills to cloud above the slider's threshold #509
Released from Later to use the week's subscription: Behind pace: 75% of the week left with 21% of its time gone, reset 2026-11-15 02:00 UTC, burning 0% an hour against 0.5% allowed; speeding up to 5 of 5 slots and releasing the next issue.
Reviewed pull #10193 at its head: ticked src/core/placement_policy.ts: pure placeFor({ ownedUsed, ownedCapacity, spillAtOwnedUse, alwaysOn, preference }) → owned | cloud with a one-sentence reason; production prefers owned; a preview spills first; an app's placement: metal|cloud in app.yaml is a preference the policy honours unless owned is full; the decision is written to the decision ledger (core/decisions.ts) and onto the meter interval, so cost knows which price applies; with no cloud body configured every decision is owned and the board says "no cloud body: bursts queue" — never silently; the platform label for owned nodes (plat.sh/site=vxrail) is a setting, not a constant, passed through to whatever body implements it; tests: below threshold → owned; above → cloud for previews first; full owned + no cloud → owned with the queue reason.
The owner's intent: run owned metal at full capacity and spill only bursts to cloud. Today every app runs in this process and the spawn seam (
src/spawn/placement.ts) only knowshosted. This run is the decision, not a new body.Acceptance:
src/core/placement_policy.ts: pureplaceFor({ ownedUsed, ownedCapacity, spillAtOwnedUse, alwaysOn, preference })→owned|cloudwith a one-sentence reason; production prefers owned; a preview spills first; an app'splacement: metal|cloudin app.yaml is a preference the policy honours unless owned is fulldecisionledger (core/decisions.ts) and onto the meter interval, so cost knows which price appliesownedand the board says "no cloud body: bursts queue" — never silentlyplat.sh/site=vxrail) is a setting, not a constant, passed through to whatever body implements itFiles: new src/core/placement_policy.ts, src/spawn/placement.ts, src/core/decisions.ts. Holds up #391 (services need a placement lever).
Part of the profit slider (#392); the shape is
docs/PROFIT.md.