resource-control/docs/optimization-cases.md
tegwick 2c2a6073ff feat(portfolio): complete RESOURCE-WP-0003 T06 optimization cases and T07 reporting
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>
2026-08-14 09:28:44 +02:00

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.

  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. Uncertaintylow, 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_evidenceproposedapproved | rejectedsuperseded.

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.