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>
This commit is contained in:
parent
54dd45c926
commit
2c2a6073ff
63 changed files with 4662 additions and 69 deletions
104
docs/evidence/RESOURCE-WP-0003-optimization-cases-2026-08-14.md
Normal file
104
docs/evidence/RESOURCE-WP-0003-optimization-cases-2026-08-14.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# RESOURCE-WP-0003 optimization cases — 2026-08-14
|
||||
|
||||
## Result
|
||||
|
||||
`RESOURCE-WP-0003-T06` established the review cadence, the decision template,
|
||||
and a fail-closed evaluator for optimization cases, and validated the process
|
||||
against the backup case and one non-storage portfolio candidate.
|
||||
|
||||
The implementation consists of:
|
||||
|
||||
- `schemas/optimization-case.schema.json` — baseline and alternatives carry
|
||||
identical decision fields, so a comparison against an undescribed status quo
|
||||
is structurally impossible;
|
||||
- `tools/optimization.py` — comparison, payback, failure-domain delta, verdicts,
|
||||
and decision-state validation;
|
||||
- `data/optimization/platform-audit-storage-2026-08.json` — the storage case;
|
||||
- `data/optimization/reef-railiance-k3s-2026-08.json` — the non-storage case;
|
||||
- `docs/optimization-cases.md` — case types, decision template, cadence, and the
|
||||
loop that returns outcomes to the next forecast;
|
||||
- 25 tests in `tests/test_optimization.py`, plus schema and case checks in
|
||||
`tools/validate.py`.
|
||||
|
||||
## Decision fields
|
||||
|
||||
T06 requires every recommendation to show baseline, alternative, one-time cost,
|
||||
recurring infrastructure and labour cost, utilization, uncertainty,
|
||||
service-level constraints, failure domains, exit path, and expected payback.
|
||||
The schema requires all ten on every option, and the evaluator refuses to
|
||||
recommend while any is `null`. Payback is computed from one-time cost and
|
||||
realised monthly saving; it is never asserted.
|
||||
|
||||
Recurring cost is split into infrastructure, internal labour, and external
|
||||
labour. This is not cosmetic: in the storage case Hetzner has the lower
|
||||
infrastructure price (EUR 6.49 against EUR 7.35) and is still EUR 29.14 per
|
||||
month more expensive, entirely on operator hours. A comparison on unit price
|
||||
alone would have inverted the result.
|
||||
|
||||
## Fail-closed behaviour
|
||||
|
||||
One unknown anywhere in the compared pair makes the comparison
|
||||
`blocked_on_evidence`. Unknowns are `null` values plus a named `unknowns` list
|
||||
that attributes each gap to an owning repository or authority. The evaluator
|
||||
also refuses invalid decision states: a blocked case cannot be `proposed` or
|
||||
`approved`, a decided case must name `approver` and `approved_on`, and a case
|
||||
with no blockers cannot claim to be blocked.
|
||||
|
||||
`reject` is a cost verdict only. The three-node cluster option raises recurring
|
||||
cost by design and buys availability instead; that argument belongs to the
|
||||
deciding authority against a declared service objective, not to the calculator.
|
||||
|
||||
## Case 1 — `opt:platform-audit-storage:2026-08` (storage)
|
||||
|
||||
Baseline is Scaleway Standard Multi-AZ, the provisional primary from T02 due
|
||||
diligence, at month-12 base-scenario demand from `tools/cost_model.py`.
|
||||
|
||||
| Option | Recurring EUR/month | Verdict |
|
||||
|---|---|---|
|
||||
| Scaleway Standard Multi-AZ (baseline) | 67.35 | — |
|
||||
| Hetzner Object Storage | 96.49 | `reject` (+29.14) |
|
||||
| Host Europe Cloud Storage | unknown | `blocked_on_evidence` |
|
||||
|
||||
Host Europe is blocked on four named gaps: current S3 orderability for this
|
||||
account, five price fields, cancellation terms, and correlated-failure
|
||||
acceptance. It has no known exit path, and it shares `provider:host-europe`
|
||||
with the compute host the backup is meant to protect.
|
||||
|
||||
This case exercises the process against real cost-model output. It is
|
||||
deliberately **not** the procurement decision, which `RESOURCE-WP-0002-T03`
|
||||
owns and human financial authority approves. The case state is
|
||||
`blocked_on_evidence` and recommends nothing.
|
||||
|
||||
## Case 2 — `opt:reef-railiance-k3s:2026-08` (non-storage)
|
||||
|
||||
Baseline is the current single-node k3s on railiance01, with the live capacity
|
||||
observation from T03 discovery: 0.564 of 4 vCPU, 5.83 of 15.62 GiB, 66.77 of
|
||||
192.69 GiB root filesystem.
|
||||
|
||||
Utilization is genuinely low — 14 percent CPU, 37 percent memory — and that is
|
||||
a real rightsizing signal. Every comparison is nevertheless blocked, for two
|
||||
independent reasons the case records rather than works around:
|
||||
|
||||
1. The railiance01 booked price is unknown, so no option has a recurring cost,
|
||||
no saving exists, and no payback can be computed.
|
||||
2. The utilization figure is a single sample taken on 2026-08-11. Mean usage is
|
||||
not a sizing basis; peak load over a billing period is owed by
|
||||
`RAIL-BS-WP-0014`.
|
||||
|
||||
Both alternatives — a smaller single server and the RAIL-BS-WP-0007 three-node
|
||||
cluster — are recorded with their unknowns attributed to `railiance-infra`
|
||||
(`RAIL-HO-WP-0008`) and `railiance-cluster` (`RAIL-BS-WP-0014`).
|
||||
|
||||
A case that refuses to conclude is the correct output here, and it is a useful
|
||||
one: it names exactly which evidence would unblock a rightsizing decision, and
|
||||
it is visible in the portfolio report until that evidence arrives.
|
||||
|
||||
## Boundaries held
|
||||
|
||||
`resource-control` produced both cases and decided neither. Financial
|
||||
implications reach `fin-hub` through `financial_handoff` under
|
||||
`docs/fin-hub-resource-control-contract-v0.1.md`; neither case has sent one,
|
||||
because neither is approved. Implementation is delegated through
|
||||
`decision.delegated_to`, which names `railiance-infra` and `railiance-cluster`
|
||||
for the cluster case. `outcome.feeds_forecast` binds each case to the
|
||||
control-cycle records that will later show whether it was right.
|
||||
Loading…
Add table
Add a link
Reference in a new issue