Skip to content

feat(historical): B2/#126 — frame-native historical (pandas out of the construction) - #129

Merged
Polichinel merged 1 commit into
developmentfrom
feat/oom-b2-frame-native-historical
Jul 27, 2026
Merged

feat(historical): B2/#126 — frame-native historical (pandas out of the construction)#129
Polichinel merged 1 commit into
developmentfrom
feat/oom-b2-frame-native-historical

Conversation

@Polichinel

Copy link
Copy Markdown
Collaborator

Part B of the run-0 OOM fix — the root cause. The historical path drops from could-not-finish-in-8-minutes/23.8 GB-OOM to a ~0.5 GB FeatureFrame + pyarrow gather.

What

  • managers/unfao.py: _read_historical_data dispatches on declared_data_format (pipeline-core's contract fn); frame branch → get_feature_frame (first production consumer of the frame path — C-40's gate has lifted). Contract-mode _save now also ships the historical artifact (an S7 gap: run 0 would have had forecasts but no actuals), behind the same interlock.
  • unfao/historical.py — the artifact builder, pandas-free, reader-identical; null-gate + unmapped-count preserved fail-loud.
  • frame_extraction.drop_months_above — frame-native clip, same degrade-open policy.

Deliberate reader-safe divergences (both verified in faoapi's code + pinned by tests)

  1. Junk row/col columns dropped — legacy would have served them as bogus targets.
  2. Values ship as scalars, not C-40 single-element lists — faoapi's _validate_feature_samples (handlers.py:374) normalizes both to the same array.

AC

  • Reader-level parity with the B1 golden: green (same real slice through both chains, compared via faoapi's reader semantics incl. null/NaN and scalar/list normalization).
  • Builder property tests: schema pinned, plain strings/float64 codes, absent-gid loud, multi-sample refused, unmapped-count.
  • Full suite 261 passed (5 known local toolchain tests aside; CI authoritative).

Closes #126. Refs #92 #89. 🤖 Generated with Claude Code

…es the construction, the artifact stays reader-identical

_read_historical_data dispatches on declared_data_format (pipeline-core's
contract fn — the one gate, never re-implemented): feature_frame descriptors
fetch via get_feature_frame → FeatureFrame, making the FAO product the frame
path's first production consumer (C-40 gate lifted). Frame-native month clip
(frame_extraction.drop_months_above; same producer-sourced boundary,
degrade-open). unfao/historical.py builds the SAME artifact faoapi's deployed
reader ingests — month_id/priogrid_id/targets/9-GAUL-cols plain parquet —
pandas-free (searchsorted gather from the injected ADR-011 lookup; sidecar
cast discipline: plain strings, float64 codes); null-gate + unmapped-count
carried over fail-loud. Deliberate divergences, both reader-safe and pinned by
tests: junk row/col columns DROPPED (the legacy chain would have shipped them
as bogus auto-detected targets) and values ship as SCALARS, not the C-40
single-element lists (faoapi's _validate_feature_samples normalizes both
identically — verified in their code).

Contract-mode gap closed: _save_contract now stages+uploads the historical
artifact alongside the wire, behind the same §11.4 interlock (S7 had scoped it
to the wire only — run 0 would have shipped forecasts with no actuals).

Reader-level parity with the B1 characterization golden: green (same slice,
frame chain vs legacy chain, compared through faoapi's reader semantics).

Closes #126 (with #113-era amendments). Refs #92, #89.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Polichinel
Polichinel merged commit 148d68b into development Jul 27, 2026
4 checks passed
@Polichinel
Polichinel deleted the feat/oom-b2-frame-native-historical branch July 27, 2026 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant