# Optimization cases — review cadence and decision template `resource-control` produces optimization cases. It does not approve them and it does not implement them. A case turns portfolio evidence into a reproducible comparison; a human or repository authority decides; the owning platform or workload repository implements; `fin-hub` records the money. Schema: `schemas/optimization-case.schema.json`. Evaluator: `tools/optimization.py`. Cases live in `data/optimization/`. ## Case types | Type | Question it answers | |---|---| | `rightsizing` | Is provisioned capacity materially larger or smaller than sustained demand? | | `consolidation` | Can separate resources share one substrate without breaking failure domains? | | `commitment` | Does a term or reserved commitment beat on-demand pricing at forecast demand? | | `renewal` | Should this contract renew, renegotiate, or lapse? | | `migration` | Should the workload move to different capacity at the same provider? | | `retirement` | Is this resource still serving anything? | | `provider_switch` | Should the same service come from a different provider? | ## Decision template Every option — the baseline included — must present the same fields. The baseline is a full option, not a footnote, because a comparison against an undescribed status quo is not a comparison. 1. **Baseline** — what is in place now, on the same terms as every alternative. 2. **Alternatives** — at least one, each independently costed. 3. **One-time cost** — migration, setup, dual-running, and the labour to do it. 4. **Recurring cost** — split into infrastructure, internal labour, and external labour. A cheaper unit price that doubles operator hours is not a saving. 5. **Utilization** — provisioned and used per capacity metric, with the observation that supports it. 6. **Uncertainty** — `low`, `medium`, or `high`, with the reasons written out. 7. **Service-level constraints** — what the option must still satisfy. 8. **Failure domains** — the evaluator reports which the alternative removes and which it newly introduces. 9. **Exit path** — how to leave the option. An option with no known exit path is blocked, not merely riskier. 10. **Expected payback** — computed, never asserted. ### Unknowns are first-class Any unknown cost, utilization, or exit path is `null`, and each blocking gap is named in the option's `unknowns` list with the repository or authority that owns it. The evaluator is fail-closed: one unknown makes the affected comparison `blocked_on_evidence` rather than optimistic. A case that cannot conclude is a valid, useful output — it names exactly what evidence would unblock it. ### Verdicts | Verdict | Meaning | |---|---| | `blocked_on_evidence` | A required decision field is unknown. No recommendation. | | `recommend` | Fully costed and saves more than EUR 5 per month. | | `no_material_change` | Fully costed, difference within EUR 5 per month. | | `reject` | Fully costed and more expensive than the baseline. | `reject` is a cost verdict only. An option that costs more may still be right — the three-node cluster case buys availability, not savings — and that argument belongs in `decision.rationale`, made by the deciding authority against a declared service objective, not by the calculator. ### Decision states `blocked_on_evidence` → `proposed` → `approved` | `rejected` → `superseded`. The evaluator enforces the transitions it can check: a case cannot be `proposed` while any comparison is blocked, cannot be `approved` while blocked, and cannot be decided without a named `approver` and `approved_on`. ## Cadence | Rhythm | Trigger | Scope | |---|---|---| | Monthly | `cadence` | Review variance from `tools/control_cycle.py`. Open a case where forecast error is attributed to demand, price, or allocation rather than data quality. | | Quarterly | `cadence` | Re-run every open case against refreshed evidence. Recompute all provider comparisons; a stale price is not evidence. | | Pre-renewal | `renewal` | Open at least 60 days before `lifecycle.renews_on` or `cancel_by`, whichever is earlier, so cancellation stays possible. | | On variance | `variance` | Sustained variance beyond the thresholds in `docs/forecast-actual-control.md`. | | On demand | `request`, `procurement`, `incident` | A workload repository, a procurement decision, or an incident that exposed a failure domain. | ## Closing the loop An approved case is not finished when it is approved. 1. `financial_handoff` carries the cost attribution key and the reference to `fin-hub` under the contract in `docs/fin-hub-resource-control-contract-v0.1.md`. 2. `decision.delegated_to` names the repositories that implement. Implementation detail is theirs; this repository states the interface and the acceptance evidence only. 3. `outcome.feeds_forecast` names the control-cycle forecast records the decision changes. The original forecast is never overwritten — a decision produces a revision, per `docs/forecast-actual-control.md`. 4. `outcome.actual_refs` collects the monthly actuals that later show whether the predicted saving materialised. A case whose actuals never arrive is an unverified case, and the next quarterly review should say so. ## Current cases | Case | Type | State | Why | |---|---|---|---| | `opt:platform-audit-storage:2026-08` | `provider_switch` | `blocked_on_evidence` | Hetzner computes and is EUR 29.14 per month dearer than Scaleway at month-12 base demand, on labour rather than storage price. Host Europe has no usable price, no cancellation terms, and shares a failure domain with the host it would protect. The procurement decision itself belongs to `RESOURCE-WP-0002-T03`. | | `opt:reef-railiance-k3s:2026-08` | `rightsizing` | `blocked_on_evidence` | Observed utilization is 14 percent CPU and 37 percent memory — a real signal from one sample. Nothing can be costed while the railiance01 booked price is unknown, so no payback exists. Blocked against `RAIL-HO-WP-0008` and `RAIL-BS-WP-0014`. |