T06: optimization-case schema, fail-closed evaluator, cadence and decision template. Every option including the baseline must present all ten decision fields; one unknown blocks the comparison. Validated on the storage case (Hetzner computes and loses to Scaleway by EUR 29.14/month on operator labour; Host Europe blocks on four named gaps) and on the non-storage reef-railiance k3s rightsizing case (low utilization is real, but nothing is costable while the railiance01 price is unknown). T07: portfolio report over coverage, lifecycle, utilization, cost, renewals, risks, open cases, and next actions, derived only from committed evidence. Portfolio spend is reported null rather than as a partial sum, unattributed cost is a named list rather than a spread, and unmeasurable resources are reported rather than dropped. RESOURCE-WP-0003 is finished; both cases remain blocked_on_evidence against live delegated records in other repositories. RESOURCE-WP-0002 is untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5.9 KiB
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.
- Baseline — what is in place now, on the same terms as every alternative.
- Alternatives — at least one, each independently costed.
- One-time cost — migration, setup, dual-running, and the labour to do it.
- Recurring cost — split into infrastructure, internal labour, and external labour. A cheaper unit price that doubles operator hours is not a saving.
- Utilization — provisioned and used per capacity metric, with the observation that supports it.
- Uncertainty —
low,medium, orhigh, with the reasons written out. - Service-level constraints — what the option must still satisfy.
- Failure domains — the evaluator reports which the alternative removes and which it newly introduces.
- Exit path — how to leave the option. An option with no known exit path is blocked, not merely riskier.
- 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.
financial_handoffcarries the cost attribution key and the reference tofin-hubunder the contract indocs/fin-hub-resource-control-contract-v0.1.md.decision.delegated_tonames the repositories that implement. Implementation detail is theirs; this repository states the interface and the acceptance evidence only.outcome.feeds_forecastnames the control-cycle forecast records the decision changes. The original forecast is never overwritten — a decision produces a revision, perdocs/forecast-actual-control.md.outcome.actual_refscollects 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. |