Repository navigation
S11 — Living docs still describe code epic #148 deleted; the doc guard's ban list was never updated #197
Description
Part of epic #181. Finishes #154, which was closed 2026-08-01 with the work partly undone. Run before S4 (#185) — see Ordering.
Background
Epic #148 deleted the retired delivery path (#149) and moved the machinery from unfao/ to contract/ (#153). Its story #154 — "Correct ADR-012 and the manager CIC to describe what the code is" was closed on 2026-08-01.
ADR-012 was corrected. The rest was not. Eighteen references to deleted code survive across four living onboarding documents:
| document | stale references |
|---|---|
README.md |
_append_metadata (:76), _clip_observed_history (:78) |
docs/architecture/role_and_seams.md |
unfao/extraction.py (:113), delivery/identity (:116), PGMDataset (:58, :126, :150) |
views_postprocessing/unfao/managers/README.md |
unfao/extraction.py (:18), _append_metadata (:28, :49), _clip_observed_history (:30), unfao/gaul_schema (:33), tests/test_append_metadata.py (:49) |
docs/CICs/UNFAOPostProcessorManager.md |
delivery/identity (:80), _clip_observed_history (:83), _delivery_description (:84), _append_metadata (:148), test_append_metadata (:148) |
Verified against the tree: _append_metadata, _clip_observed_history and _delivery_description have zero hits in views_postprocessing/**/*.py. unfao/extraction.py, delivery/identity.py and tests/test_append_metadata.py do not exist.
The manager README is the worst of them. It documents the Template Method's phases as _transform → _append_metadata and points a reader at tests/test_append_metadata.py for the contract. Both were deleted on 2026-07-31. It sits inside the package, next to the code it misdescribes, and is the first thing a contributor opens.
Why the existing guard did not catch it
tests/test_doc_accuracy.py already scans every one of these four files — _living_docs() includes the root README, docs/architecture/*.md and views_postprocessing/**/README.md, and the CIC is link-checked.
But its ban list only knows the ADR-011 era:
_BANNED = re.compile(
r"PriogridCountryMapper|mapping/README|use_disk_cache|cachetools|geopandas",
re.IGNORECASE,
)Those are the symbols C-39 deleted in June. Nothing was added when #149 and #153 deleted a fresh set in July, so the guard kept passing over documents describing code that no longer exists. The guard was not wrong; it was not updated. That is the epic's thesis in its most literal form — a check that stopped covering what it claims to cover.
This is the second "closed but undone" story issue, after #158 (finished in S3 / #195), and the seventh instance of the stale-claim class in three days.
Work
1 — Correct all four documents against the post-#148 tree.
Where a method was deleted, name what replaced it rather than dropping the row: _append_metadata became the frame-native artifact build (contract/historical.build_historical_table + assert_metadata_complete), and _clip_observed_history went with the pandas historical read. A phase table with a gap is worse than one that says where the work moved.
2 — Extend _BANNED with the #148-era symbols:
_append_metadata, _delivery_description, _clip_observed_history, LEGACY_FORECAST_FILTERS, test_append_metadata, unfao/extraction.py, unfao/frames.py, unfao/historical.py, unfao/gaul_schema, unfao/wire, delivery/identity.
3 — Judge PGMDataset line by line; do NOT blanket-ban it. Three doc hits, and they are not all the same claim:
role_and_seams.md:58asserts pipeline-core "provides the tools the steps use:ViewsDataLoader,PGMDataset". False — the bare class has zero hits in this repo's code.:126and:150explain why pandas was the wrong representation (object-dtype list-in-cell). That is legitimate comparative narration about a design this repo moved away from, and deleting it would remove the reasoning for the frame-native path.
The two surviving code hits are FAO_PGMDataset, a views-faoapi class name in a docstring — a different thing that must not be caught by a careless pattern.
4 — Leave docs/ADRs/ and reports/ alone. They narrate what was decided when it was decided. Same boundary S3 drew for the retired contract name.
Ordering — why this runs before S4 (#185)
S4's file list already includes docs/CICs/UNFAOPostProcessorManager.md ("check it does not repeat the stale claim"). Five of the eighteen hits are in that file.
More importantly, the ban list cannot be extended until all four documents are clean — turning it on with any of them stale fails the suite. So this must be one atomic story, and doing it first means S4 finds the CIC already correct and can drop that check.
Acceptance criteria
- Zero references to deleted symbols in the four living documents; the sweep script in Testing returns nothing.
_BANNEDcovers the [EPIC] One delivery path, one partner boundary — make this repo cloneable for views-crafdapi + views-productionapi #148-era deletions and the guard passes.PGMDatasetdecided line by line, with the reasoning in the diff.FAO_PGMDatasetstill permitted.- The manager README's phase table describes the phases the manager actually has, naming where deleted work went.
docs/ADRs/andreports/untouched.- S6 — Correct ADR-012 and the manager CIC to describe what the code is #154 commented explaining what it left behind, as Rename PLATFORM-001 -> The Appwrite Seam Contract in this repo's citations (cosmetic, non-blocking) #158 was.
Testing
ruff check .
pytest -q tests/test_doc_accuracy.py
pytest -q
Mutation-prove the extended ban, per repo practice:
def test_the_ban_catches_a_post_148_deleted_symbol(tmp_path):
"""A ban list that was not updated when the code changed is why this story exists."""Sweep to verify (this is the command that produced the table above):
python - <<'PY'
import pathlib
REPO = pathlib.Path(".")
DEAD = ["_append_metadata","_delivery_description","_clip_observed_history",
"LEGACY_FORECAST_FILTERS","test_append_metadata","unfao/extraction.py",
"unfao/historical.py","unfao/frames.py","unfao/gaul_schema","unfao/wire",
"delivery/identity"]
docs = [REPO/"README.md", *sorted((REPO/"docs"/"architecture").glob("*.md")),
*sorted((REPO/"views_postprocessing").rglob("README.md")),
*sorted((REPO/"docs"/"CICs").glob("*.md")), REPO/"docs"/"CLONING.md"]
for d in (x for x in docs if x.exists()):
for i, line in enumerate(d.read_text().splitlines(), 1):
for s in DEAD:
if s in line and "legacy-ok" not in line:
print(f"{d}:{i} {s}")
PY
Dependencies
None. Blocks S4 (#185) by convention rather than by code — S4's CIC check is satisfied by this.
Files
README.md,docs/architecture/role_and_seams.md,views_postprocessing/unfao/managers/README.md,docs/CICs/UNFAOPostProcessorManager.mdtests/test_doc_accuracy.py:29-32(_BANNED),:34-40(_living_docs)- S6 — Correct ADR-012 and the manager CIC to describe what the code is #154 (closed prematurely), S1 — Delete the retired delivery path; refuse an incomplete config #149 / S5 — Separate partner declarations from delivery machinery #153 (the deletions), Rename PLATFORM-001 -> The Appwrite Seam Contract in this repo's citations (cosmetic, non-blocking) #158 / S3 — Finish #158's rename, and ban the retired contract name from code #184 (the same pattern, first instance), register C-74, Cluster I
Activity
docs(accuracy): S11 #197 — living docs still described code #148 dele…
Polichinel commentedon Aug 2, 2026
Landed in #199.
Correction to this issue's own framing, on reading rather than grepping: it said "18 stale references" and implied all were defects. Ten were.
role_and_seams.mdand the CIC had largely been done properly by #154 — they narrate retirements deliberately, and Seam B says of itself that it describes the pre-2026-07-27 state and is kept because the shape of the fix is worth reading. Those got the repo's line-scopedlegacy-okmarker instead of edits.The two READMEs were never touched by #154 at all. The manager README was wrong in six places, including a claim that Appwrite settings have "no startup validation yet — tracked in #11" when þing-01 #134 added fail-loud validation and #11 is about timeouts.
Ban list 5 → 19 entries, grouped by the PR that deleted each,
(?<!FAO_)PGMDatasetlookbehind sparing views-faoapi's live class. Mutation-tested. New test pins thatlegacy-okstays line-scoped — a marker that leaked to a whole file would silently disable the guard it excuses.Review caught two things in my own work: the failure message had lost the path while three living docs are named
README.md, and I wrote an unverified claim into the CIC about forecast provenance in the run manifest. Verified againstrun_manifest.pyand corrected — writing an unchecked claim into a contract document, in the story about unchecked claims, is the habit this epic is against.