You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Origin: executes #3 ("Broaden scope: accept reconciliation from views-reporting") and the views-reporting side views-platform/views-reporting#72 ("Reconciliation is not reporting — migrate to views-postprocessing").
Authored as a context-rich, solution-open brief. Approaches are proposals, not prescriptions.
Why
Forecast reconciliation makes PRIO-GRID-month (pgm) predictions sum to their country-month (cm) totals — a post-forecast operation called by ensemble managers before any reporting/evaluation/delivery. It lives in views-reporting by accident (extracted there alongside visualisation code). That repo's own roadmap, risk register (C-24: "torch leaves with it"), and frames-adoption plan all say it should move here, and it is cleanly separable (zero ties to reporting/plotting/Appwrite).
Moving it here gives it the right roof (post-processing, not reporting), removes views-reporting's torch dependency (reconciliation is its only consumer), and makes the dependency direction clean (pipeline-core → views-postprocessing).
Where we are
Slice 1 is done (PR #30): the leaf algorithm reconcile_proportional was ported to pure numpy and proven bit-for-bit against the untouched views-reporting torch oracle (tests/test_reconciliation_parity.py, max abs diff 0.0). C-37 records that this is the pragmatic per-draw method (FPP3 top-down forecast-proportions), to be upgraded to principled probabilistic reconciliation after the migration is wired.
This epic is everything after the leaf: orchestration, country↔grid grouping, end-to-end parity, the cross-repo repoint, and the phase-out.
Desired end state
Reconciliation runs end-to-end in views-postprocessing, frames-native, with no torch, no pandas, no viewser, no wandb in the path; its output is proven to reproduce the frozen views-reporting pipeline on a realistic fixture; pipeline-core's ensemble managers call it here; and the views-reporting copy (plus its torch dep) is removed.
Scope
✅ In: orchestration (ReconciliationModule equivalent), country↔grid grouping via views_frames.cross_level_align, frames-native validation, the end-to-end parity gate, the pipeline-core repoint, and the views-reporting phase-out.
❌ Out (future, not this epic):
Changing the algorithm. Migration is parity-preserving; the upgrade to principled probabilistic reconciliation (the IJF paper, C-37) is a separate follow-on epic, gated on this one completing.
Editing views-reporting before phase-out. It stays frozen as the parity oracle until the final story.
Reconciling the GAUL vs VIEWS country-id systems. For parity we inject the oracle's VIEWS country_id mapping; whether to later source it from our GAUL lookup (admin1_gaul0_code) is a separate decision (see the first story).
The one decision to retire first
The oracle groups grid cells by VIEWS country_id fetched from viewser (network; views_reporting/metadata/entity_metadata.py). Our GAUL lookup uses admin1_gaul0_code — a different id system. For parity we must group by the same VIEWS country_id, injected (the leaf never embeds geography — views-frames ADR-014). Story S0 captures the oracle fixture offline and records this decision.
Stories
Execution order (full checklist in the tracking issue #41):
A frames-native reconciliation module reproduces the frozen views-reporting pipeline on a realistic fixture (end-to-end parity), offline (CI needs no torch / views-reporting / viewser).
No torch, pandas, viewser, or wandb in the reconciliation path here.
A CIC documents the orchestration class (repo convention, ADR-006).
pipeline-core ensemble managers call reconciliation in views-postprocessing.
Reconciliation (and torch) are removed from views-reporting; views-reporting#72 closed.
C-37 (principled-upgrade) remains open and is handed to its follow-on epic.
Origin: executes #3 ("Broaden scope: accept reconciliation from views-reporting") and the views-reporting side views-platform/views-reporting#72 ("Reconciliation is not reporting — migrate to views-postprocessing").
Why
Forecast reconciliation makes PRIO-GRID-month (pgm) predictions sum to their country-month (cm) totals — a post-forecast operation called by ensemble managers before any reporting/evaluation/delivery. It lives in views-reporting by accident (extracted there alongside visualisation code). That repo's own roadmap, risk register (C-24: "torch leaves with it"), and frames-adoption plan all say it should move here, and it is cleanly separable (zero ties to reporting/plotting/Appwrite).
Moving it here gives it the right roof (post-processing, not reporting), removes views-reporting's torch dependency (reconciliation is its only consumer), and makes the dependency direction clean (
pipeline-core → views-postprocessing).Where we are
Slice 1 is done (PR #30): the leaf algorithm
reconcile_proportionalwas ported to pure numpy and proven bit-for-bit against the untouched views-reporting torch oracle (tests/test_reconciliation_parity.py, max abs diff0.0). C-37 records that this is the pragmatic per-draw method (FPP3 top-down forecast-proportions), to be upgraded to principled probabilistic reconciliation after the migration is wired.This epic is everything after the leaf: orchestration, country↔grid grouping, end-to-end parity, the cross-repo repoint, and the phase-out.
Desired end state
Reconciliation runs end-to-end in views-postprocessing, frames-native, with no torch, no pandas, no viewser, no wandb in the path; its output is proven to reproduce the frozen views-reporting pipeline on a realistic fixture; pipeline-core's ensemble managers call it here; and the views-reporting copy (plus its torch dep) is removed.
Scope
✅ In: orchestration (
ReconciliationModuleequivalent), country↔grid grouping viaviews_frames.cross_level_align, frames-native validation, the end-to-end parity gate, the pipeline-core repoint, and the views-reporting phase-out.❌ Out (future, not this epic):
country_idmapping; whether to later source it from our GAUL lookup (admin1_gaul0_code) is a separate decision (see the first story).The one decision to retire first
The oracle groups grid cells by VIEWS
country_idfetched from viewser (network;views_reporting/metadata/entity_metadata.py). Our GAUL lookup usesadmin1_gaul0_code— a different id system. For parity we must group by the same VIEWScountry_id, injected (the leaf never embeds geography — views-frames ADR-014). Story S0 captures the oracle fixture offline and records this decision.Stories
Execution order (full checklist in the tracking issue #41):
planningneeds-decisionimplementation(after Capture the offline parity oracle + decide the country↔grid id system #32)cross_level_align·implementation(after CM/PGM → PredictionFrame adapters #33)implementation(after CM/PGM → PredictionFrame adapters #33)implementation(after Country↔grid grouping core via cross_level_align #34, Frames-native reconciliation validation guards #35)testing(after ReconciliationModule orchestration (numpy-native; drop wandb + multiprocessing) #36)documentation(after ReconciliationModule orchestration (numpy-native; drop wandb + multiprocessing) #36)implementationblocked(after End-to-end reconciliation parity gate vs frozen views-reporting #37)implementationblocked(after Wiring: expose reconciliation API + pipeline-core ensemble repoint #39)Epic acceptance criteria
torch,pandas,viewser, orwandbin the reconciliation path here.