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
123
docs/forecast-actual-control.md
Normal file
123
docs/forecast-actual-control.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# Forecast-to-actual resource control
|
||||
|
||||
## Why the €2.89, €5.14, €62.89, and €65.14 figures differ
|
||||
|
||||
They describe two volumes and two cost scopes:
|
||||
|
||||
| Figure | Stored volume | Scope | Calculation |
|
||||
| --- | ---: | --- | --- |
|
||||
| €2.89 | 180 GB | infrastructure only | 180 × €0.01606 |
|
||||
| €62.89 | 180 GB | infrastructure + internal labor | €2.89 + 1 h × €60 |
|
||||
| €5.14 | 320 GB | infrastructure only | 320 × €0.01606 |
|
||||
| €65.14 | 320 GB | infrastructure + internal labor | €5.14 + 1 h × €60 |
|
||||
|
||||
The older €62.89 estimate was not “storage without elastic cost”; it already
|
||||
included the €60 monthly operator allowance. The normalized table introduced a
|
||||
different stored volume and showed infrastructure separately. Future reports
|
||||
must always label both `stored_gb` and cost scope.
|
||||
|
||||
## Control records
|
||||
|
||||
A forecast is a timestamped, immutable record of what was believed at decision
|
||||
time. The initial base forecast is
|
||||
`data/forecasts/platform-audit-storage-scaleway-base-2026-08.json`. Do not edit
|
||||
it after actual evidence exists. If assumptions change, create a new forecast
|
||||
with a new creation date and retain the prior one so forecast accuracy remains
|
||||
auditable.
|
||||
|
||||
After every billing month, record a technical `usage_observation` under
|
||||
`data/actuals/`. Authoritative booked financial facts come from fin-hub and
|
||||
are joined by reference; resource-control does not originate a second booked
|
||||
actual.
|
||||
The required cost and usage proxies are:
|
||||
|
||||
- database size and provider stored bytes;
|
||||
- WAL volume;
|
||||
- write and read requests;
|
||||
- restore-test egress;
|
||||
- infrastructure invoice cost;
|
||||
- internal operations hours and valued labor cost;
|
||||
- total attributable cost;
|
||||
- backup success, maximum observed RPO, and restore RTO when measured.
|
||||
|
||||
Provider stored bytes are intentionally distinct from logical database size.
|
||||
They expose base-backup retention, WAL, compression, versioning, incomplete
|
||||
multipart uploads, and lifecycle behavior. Invoice cost is distinct from the
|
||||
provider's usage estimator and must reconcile to non-secret billing evidence.
|
||||
|
||||
## Error calculation and review
|
||||
|
||||
`make variance ACTUAL=data/actuals/YYYY-MM.json` reports signed error and
|
||||
absolute percentage error for each numeric proxy. Initially review rather than
|
||||
automatically rewrite assumptions:
|
||||
|
||||
- investigate infrastructure cost error above 10%;
|
||||
- investigate stored-byte or WAL error above 20%;
|
||||
- investigate any unplanned egress or request-class charge;
|
||||
- investigate labor error above 1 hour or 25%;
|
||||
- investigate every backup failure, RPO breach, or restore-RTO regression.
|
||||
|
||||
After three comparable months, calculate mean absolute percentage error by
|
||||
proxy and recalibrate the next forecast. Avoid MAPE where the forecast is zero;
|
||||
use absolute error and explain the new activity instead. Separate forecast
|
||||
error from price variance: a bill can differ because usage was wrong, the rate
|
||||
changed, tax/discount treatment differed, or an unmodeled SKU appeared.
|
||||
|
||||
Quarterly provider comparison should use the latest actual trailing three
|
||||
months, the next 12-month forecast, one monthly restore, an exit event, and
|
||||
observed—not aspirational—operator labor.
|
||||
|
||||
## General portfolio control record
|
||||
|
||||
The storage-specific v0.1 observation remains valid for the backup procurement
|
||||
case. New portfolio controls use
|
||||
`schemas/resource-control-cycle.schema.json`, whose resource-specific
|
||||
`usage_proxies` allow the same comparison mechanism to cover storage, VMs or
|
||||
cluster compute, shared platform services, managed services, and future
|
||||
resource types without pretending they share the same utilization unit.
|
||||
|
||||
Each record separates:
|
||||
|
||||
- provisioned and used capacity, with a fixed, elastic, or hybrid model;
|
||||
- infrastructure, internal labor, and external labor cost;
|
||||
- booked financial facts, referenced rather than copied from fin-hub;
|
||||
- allocation method, driver, version, and unattributed residual;
|
||||
- service constraints and their units;
|
||||
- low/base/high forecast scenario or observed actual;
|
||||
- evidence and uncertainty.
|
||||
|
||||
Forecast records are append-only. A changed forecast receives a new
|
||||
`record_id`, creation time, and `revision_of` reference. Actuals must name the
|
||||
exact original `forecast_ref`; a later revision must never replace the
|
||||
decision-time baseline when measuring forecast error.
|
||||
|
||||
Run a generic comparison with:
|
||||
|
||||
```sh
|
||||
make control-cycle FORECAST=examples/control-cycle/storage-forecast.json \
|
||||
ACTUAL=examples/control-cycle/storage-actual.json
|
||||
```
|
||||
|
||||
The examples cover storage, `reef-railiance` cluster compute, and the shared
|
||||
`apps-pg` service. Their numbers are illustrative contract fixtures, not booked
|
||||
facts. Operational records replace their evidence references after the owner
|
||||
workplans publish observations.
|
||||
|
||||
## Variance attribution
|
||||
|
||||
Every material variance is assigned to one of six controlled categories:
|
||||
|
||||
- `demand`: the amount of consumed service differed;
|
||||
- `provider_price`: rate, discount, tax, currency, or billed SKU differed;
|
||||
- `allocation`: a shared-cost driver or attribution changed;
|
||||
- `labor`: internal or external effort differed;
|
||||
- `model`: a formula, assumption, capacity behavior, or omitted component was
|
||||
wrong;
|
||||
- `data_quality`: evidence is missing, late, inconsistent, or uses a different
|
||||
unit.
|
||||
|
||||
The comparator defaults usage differences to demand, infrastructure cost to
|
||||
provider price, and labor fields to labor, while preserving explicit
|
||||
attribution supplied with the actual. Missing proxies and unit mismatches fail
|
||||
closed as data-quality errors. Attribution explains an error; it does not
|
||||
rewrite the forecast.
|
||||
Loading…
Add table
Add a link
Reference in a new issue