Skip to content

S0 — Scaffold the delivery/ contract package + unfao/extraction.py seam + package hygiene #61

Description

@Polichinel

Epic: #51 · foundational — every other story depends on this · story implementation

Why

The input-integrity guards must be representation-agnostic invariants (so they survive the pandas→views-frames migration and are reusable by the coming UN agencies), with pandas isolated to a single seam, and called by — not inherited into — the manager. This story stands up that structure once, so S1–S5 each drop in cleanly. It also clears the package hygiene that makes unfao/ "scream what it does."

Mirror the clean convention already used by views_postprocessing/reconciliation/ (one concept per file).

Work

  • Create views_postprocessing/delivery/ (partner-agnostic, representation-free): an __init__.py and the home for the coming invariant modules (coverage.py, observed_range.py, identity.py, provenance.py) + a constants module (region→count, the 82 gids). No import pandas anywhere under delivery/.
  • Create views_postprocessing/unfao/extraction.py: the FAO-local pandas→primitives seam (e.g. cells_of(df) -> set[int], months_of(df) -> np.ndarray, file_metadata(...) -> dict). The only representation-aware module the guards are fed from.
  • Wire the manager to call, not inherit: add a single delivery-validation step the manager invokes (initially a no-op pass-through) — extract → call guards → raise — so S1–S5 register their checks there. Do not add guard logic as methods of UNFAOPostProcessorManager.
  • Package hygiene: delete the orphaned unfao/frames.py (unused conformance artifact) and the dead unfao/mapping/ husk (C-39 leftover); fix the "frame" name overload in enrichment.py (a pd.DataFrame is not a "prediction frame").

Acceptance criteria

  • views_postprocessing/delivery/ exists and imports cleanly; nothing under it imports pandas.
  • views_postprocessing/unfao/extraction.py exists and is the sole pandas-aware extraction module.
  • The manager has a single, called (not inherited) delivery-validation hook that S1–S5 plug into.
  • unfao/frames.py and unfao/mapping/ are gone; enrichment.py no longer calls a DataFrame a "prediction frame".
  • In tests/test_input_integrity_design_contract.py, the scaffold/hygiene stubs (test_delivery_contract_package_exists, test_delivery_invariants_are_pandas_free, test_extraction_seam_is_isolated_in_one_module, test_enrichment_does_not_call_a_dataframe_a_prediction_frame, test_no_lingering_mapping_directory) flip from xfail to passing and their xfail markers are removed.

Validation

ruff check . clean; PYTHONPATH=. pytest -q green (the design-contract stubs become real passing assertions).

Files

views_postprocessing/delivery/ (new), views_postprocessing/unfao/extraction.py (new), views_postprocessing/unfao/managers/unfao.py (the call hook), views_postprocessing/unfao/enrichment.py (naming), delete views_postprocessing/unfao/frames.py + unfao/mapping/, tests/test_input_integrity_design_contract.py.

Metadata

Metadata

Assignees

No one assigned

    Labels

    implementationCode implementation workstoryA single reviewable unit of an epic

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions