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.

Activity

  1. Polichinel commented on Jun 26, 2026

    @Polichinel
    CollaboratorAuthor

    Correction (during S0 kickoff): unfao/frames.py is NOT dead — tests/test_views_frames_conformance.py:24 imports to_prediction_frame/to_target_frame from it (the views-frames conformance proof). It is orphaned from delivery but is the live conformance adapter. So do not delete it. Its only sin is living under unfao/ (it's a views-frames-adoption concern, not FAO delivery) — relocating/renaming it is a separate views-frames-adoption task, out of this epic's scope. S0 hygiene is now: delete the dead unfao/mapping/ husk + fix the enrichment.py 'frame' naming only.

  2. Polichinel commented on Jun 26, 2026

    @Polichinel
    CollaboratorAuthor

    Delivered and merged to development via #64 (input-integrity sprint S0–S6). ruff clean, 126 passed / 44 xfailed. Closing — the auto-close keyword did not fire because #64 merged into development, not the default branch. Live-run validation of the residual contracts (C-25 identity name/loa, C-43 enrichment equivalence) is tracked in the risk register and exercised by the go-global run (views-models#127).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    implementationCode implementation workstoryA single reviewable unit of an epic

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions