{"generated_at":"2026-05-23T20:26:35.889811+00:00","metrics":{"algorithm":"XGBoost + isotonic, per-horizon (K=6,12,24)","best_horizon":6,"feature_columns":["hour_of_day","hour_sin","hour_cos","day_of_week","dow_sin","dow_cos","is_weekend","n_evidence_last_6h","n_evidence_last_24h","n_block_last_6h","n_block_last_24h","block_rate_last_6h","block_rate_last_24h","asn_diversity_last_24h","country_base_rate"],"feature_provenance":"build-hourly-forecast-features.py — last 90d evidence, country panel, hourly rolling 6h/24h","generated_at":"2026-05-21T14:26:09.918500+00:00","holdout_days":30,"honest_caveats":["evidence rows cluster at hour 00 because OONI + CensoredPlanet land at daily granularity; treat hourly precision as an UPPER BOUND, not ground truth","incident first_seen is also often midnight UTC; targets inherit that coarseness","30-day temporal holdout, no country leakage. Per-country AUC is graded only on countries whose holdout has BOTH classes AND where the model gave a non-degenerate ranking (excluding the AUC=0.5 ties from single-class or flat predictions). n_countries_meaningful vs n_countries_with_auc shows the split.","calibration is per-horizon isotonic, NOT ACI-online — interval bounds are static","low-evidence countries are filtered out (MIN_EVIDENCE_24H>=1 in features); the model explicitly does NOT score 'no data' countries — endpoint returns 503 in that case","feature importance top driver is typically 'country_base_rate' — the model is largely learning WHICH countries shut things down, with hourly+rolling features modulating risk"],"horizons":[6,12,24],"lookback_days":90,"n_countries":45,"passed_promote_floor":true,"passing_horizons":[6,12,24],"per_horizon":{"6":{"auc_holdout":0.7413940062505148,"feature_importance_gain":{"asn_diversity_last_24h":0.03625515475869179,"block_rate_last_24h":0.015591480769217014,"block_rate_last_6h":0.017203930765390396,"country_base_rate":0.05966554954648018,"day_of_week":0.036601267755031586,"dow_cos":0.055941030383110046,"dow_sin":0.029961539432406425,"hour_cos":0.11702489852905273,"hour_of_day":0.3229773938655853,"hour_sin":0.234930157661438,"is_weekend":0,"n_block_last_24h":0.02113277278840542,"n_block_last_6h":0.0218970887362957,"n_evidence_last_24h":0.01663034036755562,"n_evidence_last_6h":0.014187357388436794},"mean_per_country_auc":0.6947488235386559,"median_per_country_auc":0.7214471726190476,"median_per_country_auc_incl_degenerate":0.5,"n_countries_meaningful":11,"n_countries_with_auc":17,"n_holdout":27780,"n_holdout_positive":338,"n_train":47790,"n_train_positive":639,"per_country_auc":{"AE":null,"AZ":0.7779477466977467,"BD":0.4957983193277311,"BO":null,"BY":0.4789915966386555,"CN":null,"CU":null,"DZ":null,"EG":0.4942528735632184,"ET":null,"FR":null,"GA":null,"GB":0.5,"GN":null,"ID":null,"IN":null,"IQ":0.5,"IR":null,"JO":0.9064327485380119,"KH":null,"KW":null,"KZ":0.49159663865546216,"LB":null,"MA":0.5,"MM":null,"MY":null,"NG":null,"NI":null,"OM":0.5,"PK":0.7214471726190476,"QA":0.9870689655172413,"RU":0.5,"RW":null,"SA":null,"SG":null,"SY":null,"TH":null,"TN":0.48589341692789967,"TR":null,"TT":null,"TZ":0.9209849683544304,"US":null,"UZ":0.8818226120857701,"VE":null,"VN":0.5},"promote":true,"target":"y_6h"},"12":{"auc_holdout":0.7235362216110466,"feature_importance_gain":{"asn_diversity_last_24h":0.0504310168325901,"block_rate_last_24h":0.02730320394039154,"block_rate_last_6h":0.03298516198992729,"country_base_rate":0.11824194341897964,"day_of_week":0.05639644339680672,"dow_cos":0.09140961617231369,"dow_sin":0.057636164128780365,"hour_cos":0.01715558022260666,"hour_of_day":0.23483702540397644,"hour_sin":0.20687995851039886,"is_weekend":0,"n_block_last_24h":0.030598735436797142,"n_block_last_6h":0.025234326720237732,"n_evidence_last_24h":0.02651539072394371,"n_evidence_last_6h":0.024375449866056442},"mean_per_country_auc":0.6949979616280757,"median_per_country_auc":0.6904289127837515,"median_per_country_auc_incl_degenerate":0.5,"n_countries_meaningful":12,"n_countries_with_auc":17,"n_holdout":27780,"n_holdout_positive":650,"n_train":47790,"n_train_positive":1287,"per_country_auc":{"AE":null,"AZ":0.7924133811230587,"BD":0.4915254237288136,"BO":null,"BY":0.9746835443037974,"CN":null,"CU":null,"DZ":null,"EG":0.5884444444444444,"ET":null,"FR":null,"GA":null,"GB":0.5,"GN":null,"ID":null,"IN":null,"IQ":0.5,"IR":null,"JO":0.9400253790155614,"KH":null,"KW":null,"KZ":0.4957627118644068,"LB":null,"MA":0.5,"MM":null,"MY":null,"NG":null,"NI":null,"OM":0.5,"PK":0.39553285256410253,"QA":0.9653679653679654,"RU":0.48778735632183906,"RW":null,"SA":null,"SG":null,"SY":null,"TH":null,"TN":0.46943573667711597,"TR":null,"TT":null,"TZ":0.8561949608610568,"US":null,"UZ":0.8828017832647462,"VE":null,"VN":0.5},"promote":true,"target":"y_12h"},"24":{"auc_holdout":0.8008427864612493,"feature_importance_gain":{"asn_diversity_last_24h":0.07136110216379166,"block_rate_last_24h":0.047956254333257675,"block_rate_last_6h":0.03982790187001228,"country_base_rate":0.20445679128170013,"day_of_week":0.10725647956132889,"dow_cos":0.12822026014328003,"dow_sin":0.12170427292585373,"hour_cos":0.020850317552685738,"hour_of_day":0.020121980458498,"hour_sin":0.008927100338041782,"is_weekend":0.052876438945531845,"n_block_last_24h":0.05582097917795181,"n_block_last_6h":0.028338029980659485,"n_evidence_last_24h":0.04589135944843292,"n_evidence_last_6h":0.04639069363474846},"mean_per_country_auc":0.6905508395411702,"median_per_country_auc":0.6667504794950022,"median_per_country_auc_incl_degenerate":0.5,"n_countries_meaningful":12,"n_countries_with_auc":17,"n_holdout":27780,"n_holdout_positive":1234,"n_train":47790,"n_train_positive":2601,"per_country_auc":{"AE":null,"AZ":0.6328691848058046,"BD":0.4339080459770115,"BO":null,"BY":0.991561181434599,"CN":null,"CU":null,"DZ":null,"EG":0.7006317741841999,"ET":null,"FR":null,"GA":null,"GB":0.5,"GN":null,"ID":null,"IN":null,"IQ":0.5,"IR":null,"JO":0.9004184210181141,"KH":null,"KW":null,"KZ":0.4640804597701149,"LB":null,"MA":0.5,"MM":null,"MY":null,"NG":null,"NI":null,"OM":0.5,"PK":0.5520044191919192,"QA":0.9783549783549783,"RU":0.45982142857142855,"RW":null,"SA":null,"SG":null,"SY":null,"TH":null,"TN":0.4353035143769968,"TR":null,"TT":null,"TZ":0.8064139006051715,"US":null,"UZ":0.9312427662037037,"VE":null,"VN":0.5},"promote":true,"target":"y_24h"}},"promote_floor_auc":0.6,"schema":"voidly-hourly-forecast/v1"},"schema":"voidly-hourly-forecast-info/v1","summary":{"algorithm":"XGBoost + isotonic, per-horizon (K=6,12,24)","best_horizon":6,"horizons":[6,12,24],"passed_promote_floor":true,"passing_horizons":[6,12,24],"promote_floor_auc":0.6},"_voidly_pay":{"claim_did":"https://voidly.ai/pay/claim","for_builders":"https://voidly.ai/pay/for-builders","marketplace":"https://api.voidly.ai/v1/pay/marketplace","live_demo":"https://huggingface.co/spaces/emperor-mew/voidly-pay","universal_proxy":{"url":"https://api.voidly.ai/v1/pay/proxy","example":"https://api.voidly.ai/v1/pay/proxy?u=<https-url>&to=did:voidly:<your-did>&price=0.01","page":"https://voidly.ai/pay/proxy","note":"Paywall any public HTTPS URL with one query param. No SDK install required."},"install":{"typescript":"npm install @voidly/pay","python":"pip install voidly-pay","langchain":"pip install voidly-pay-langchain","vercel_ai":"npm install @voidly/pay-vercel-ai","mcp":"npx @voidly/pay-mcp","cli":"npm install -g @voidly/pay-cli"},"note":"Voidly Pay is the open agent-to-agent payment rail. Claim a DID + 10 starter credits in 60s, or paywall any URL via the universal proxy with one query param."}}