Skip to content

S11 — Living docs still describe code epic #148 deleted; the doc guard's ban list was never updated #197

Closed

Description

@Polichinel

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:58 asserts pipeline-core "provides the tools the steps use: ViewsDataLoader, PGMDataset". False — the bare class has zero hits in this repo's code.
  • :126 and :150 explain 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

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

Activity

  1. added
    documentationImprovements or additions to documentation
    storyA single reviewable unit of an epic
    testingTest/parity/validation work
    on Aug 2, 2026
  2. added a commit that references this issue on Aug 2, 2026
  3. Polichinel commented on Aug 2, 2026

    @Polichinel
    CollaboratorAuthor

    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.md and 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-scoped legacy-ok marker 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_)PGMDataset lookbehind sparing views-faoapi's live class. Mutation-tested. New test pins that legacy-ok stays 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 against run_manifest.py and corrected — writing an unchecked claim into a contract document, in the story about unchecked claims, is the habit this epic is against.

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

    documentationImprovements or additions to documentationstoryA single reviewable unit of an epictestingTest/parity/validation work

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions