Skip to content

S8 — Rewrite the post-delivery correction procedure for the delivery that exists (C-22, #15) #189

Description

@Polichinel

Part of epic #181. Closes register C-22 (Tier 3) and finishes #15. Depends on S5.

Background

#15 was filed on 2026-06-02 and describes a system that no longer exists. Its procedure reads:

  1. Clear stale disk cache
  2. Re-run pipeline with corrected shapefiles/code
  3. Re-upload corrected files to Appwrite
  4. Notify UN FAO that previous delivery was affected
  5. FAO retracts or replaces old data in their systems

Step 1's disk cache was deleted with the runtime mapper (C-39, PR #42). Step 2's shapefiles went with it — 774 MB of LFS assets, removed. The delivery is now the ADR-013 frame-native wire: 108 arrow shards, a §5 GAUL sidecar, a run manifest committed last, and a store document the consumer filters on by name.

C-22's own trigger has meanwhile fired:

"When the run-0 integrity verification (#131 q1) or any FAO/faoapi query surfaces a suspect delivered value — follow the correction procedure; issue #15 must produce one first."

Run-0 delivered on 2026-07-27: rusty_bucket_forecasting_20260727_095355, 64,742 cells, 28,356,996 rows, live in unfao_bucket and being served by views-faoapi. There is data in a partner's store and no written way to correct it.

This is the concern C-43 kept pointing at. C-43's forward-check proved transcription fidelity end to end, but explicitly could not judge assignment correctness — that is views-datafactory#387, the degree-based area math that distorts by up to ~2× at 60°N and could flip the winning polygon for high-latitude border cells. If #387 resolves badly, the delivered data is wrong and this procedure is what gets used.

Work

Rewrite the correction procedure against the delivery that exists. Suggested home: docs/operations/correction_procedure.md, with docs/CLONING.md and the register pointing at it.

It must answer, concretely:

  1. Which deliveries are affected? The store carries run_id, and after S5 every delivery carries a lookup_version that cannot silently be "unknown". State how to enumerate affected runs from those two facts. (This is why the story depends on S5 — the identifying field has to be trustworthy before a procedure can rest on it.)
  2. What does a correction look like on the wire? ADR-013 commits the manifest last, which is the contract's own atomicity mechanism. Does a correction supersede a run, or replace its shards? Read §4 and §11 before writing — do not invent a mechanism the contract does not have.
  3. What does the consumer do? views-faoapi selects by the store document's name and by manifest. Whether a corrected run is found depends on selection, which is exactly the defect class of C-73 (newest-manifest-wins over a broad filter) and of Manifest must declare {maturity, source, required-schema-version} + stamp them — faoapi fail-visible selection contract (faoapi ADR-033 / #244) #133 (manifest must declare maturity/source). Cite them; do not re-solve them here.
  4. Who tells the UN FAO, and how? — see Decisions below.
  5. What must be preserved? A retraction that destroys the evidence makes the post-mortem impossible. State what is kept.

Keep it short and executable. This is an operational runbook, not an ADR: a person following it at 22:00 after a bad delivery should not have to read three other documents first.

Decisions needed from the operator — this is why the issue carries needs-decision

Per CLAUDE.md, anything touching an external party is Simon's to decide, not this seat's. Two questions must be answered before the document can be finished, and both should be asked in plain language:

  • Who contacts the UN FAO when a delivery is found wrong, through what channel, and how fast? Right now nobody has said. The rest of the procedure is engineering and can be drafted without this.
  • Does FAO expect us to retract, or to supersede? These need different wire behaviour, and it is a question for them, not for us.

Draft everything else first. Deliver the document with these two sections marked as awaiting the operator's answer rather than blocking the whole story on them — that is the standing instruction for uncertainty mid-task.

Acceptance criteria

Testing

Documentation, so validation is doc-accuracy rather than behaviour:

  • Extend tests/test_doc_accuracy.py to assert the new document does not mention the retired mechanisms (shapefile, disk cache, geopandas) — the same ban pattern that keeps C-39's deletion from reverting in prose.
  • Assert the document exists and names run_id and lookup_version, so a future edit cannot quietly drop the identification step. This mirrors test_clone_readiness.py::test_the_cloning_guide_exists_and_names_what_must_be_supplied.
ruff check .
pytest -q tests/test_doc_accuracy.py
pytest -q

Dependencies

Depends on S5 — the procedure's identification step rests on lookup_version being reliable.

Files

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationneeds-decisionRequires a human decision before proceedingstoryA 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