106 lines
5.9 KiB
Markdown
106 lines
5.9 KiB
Markdown
|
|
# 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`. |
|