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
25
tests/test_variance.py
Normal file
25
tests/test_variance.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parents[1] / "tools"))
|
||||
from variance import compare
|
||||
|
||||
|
||||
class VarianceTest(unittest.TestCase):
|
||||
def test_reports_signed_error_and_absolute_percentage_error(self):
|
||||
base = {"period":"2026-09","database_gb":5,"stored_gb":100,"wal_gb":10,"restore_egress_gb":5,"write_requests":100,"read_requests":50,"infrastructure_eur":10,"internal_labor_hours":1,"internal_labor_eur":60,"total_eur":70}
|
||||
actual_row = dict(base, stored_gb=120, infrastructure_eur=12, total_eur=72)
|
||||
result = compare({"created_at":"2026-08-10T00:00:00Z","rows":[base]}, {"provider_id":"test","rows":[actual_row]})
|
||||
stored = result["rows"][0]["metrics"]["stored_gb"]
|
||||
self.assertEqual(20, stored["error"])
|
||||
self.assertEqual(20, stored["absolute_percentage_error"])
|
||||
|
||||
def test_zero_forecast_has_no_percentage_error(self):
|
||||
base = {"period":"2026-09","database_gb":0,"stored_gb":0,"wal_gb":0,"restore_egress_gb":0,"write_requests":0,"read_requests":0,"infrastructure_eur":0,"internal_labor_hours":0,"internal_labor_eur":0,"total_eur":0}
|
||||
result = compare({"created_at":"x","rows":[base]}, {"provider_id":"test","rows":[dict(base, wal_gb=1)]})
|
||||
self.assertIsNone(result["rows"][0]["metrics"]["wal_gb"]["absolute_percentage_error"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue