Skip to content

Lift gtdb_ground's curation-event appender into curate/, so line-editing writers can use it #526

Description

@realmarcin

Follow-up from the #325 PR, which itemises 9 tools that edit kb/communities records in place and append no curation event:

scripts/apply_strain_designations.py    scripts/fix_reference_formats.py
scripts/apply_taxonomy_corrections.py   scripts/suggest_related_media.py
scripts/backfill_metals.py              scripts/term_fix_apply.py
scripts/chebi_fix_apply.py              scripts/term_remap.py
scripts/drop_obsolete_go_bp.py

They are gated (a new one has to be classified) but not fixed, and the reason they were not fixed in that PR is structural rather than effort.

Why record_curation_event does not reach them

communitymech.curate.curation_event.record_curation_event appends to a parsed dict and expects the caller to dump it. These nine are line editors: they operate on path.read_text().splitlines(), apply regex substitutions, and write_text the result. That is deliberate — a YAML round-trip would reflow every record it touches, which is why term_remap describes itself as "text-only edits".

So appending an event means inserting YAML text at the right place, with the right indentation, without disturbing anything else.

That code already exists, privately

scripts/gtdb_ground.py has _append_curation_event, written for #395, and it already handles the parts that are easy to get wrong:

  • the insertion point — an earlier version scanned for the first column-0 key and put the new event above the existing history, because - timestamp: is itself column-0. The fix was anchoring on ^[A-Za-z_].
  • idempotence — an unconditional append meant every re-run grew the history, so it short-circuits when the edit is a no-op.
  • the write guard_assert_only_grounding_changed takes a curation_event parameter and permits at-most-one appended entry, so the event cannot smuggle in other changes.

Every one of those is a bug someone else will re-hit if nine scripts each grow their own version.

Proposed

Lift it to communitymech.curate.curation_event beside record_curation_event — something like append_curation_event_text(lines, event) -> list[str] — keep gtdb_ground.py calling it so it stays exercised by the existing tests/test_gtdb_curation_history.py, then wire the nine. Each fixed writer removes a line from _OWED in tests/test_writers_leave_a_trace.py, and test_neither_list_has_rotted already fails if one gains a trace and stays listed.

Worth doing in more than one PR: the lift plus one writer first, to confirm the shared helper works outside its original caller before nine call sites depend on it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions