Skip to content

fix(er): make the clerical review loop round-trip and keep cluster identity - #361

Merged
kevincostner17 merged 1 commit into
mainfrom
fix/er-review-loop
Sep 15, 2026
Merged

kevincostner17 merged 1 commit into
mainfrom
fix/er-review-loop

Conversation

@kevincostner17

Copy link
Copy Markdown
Contributor

Summary

Fixes the export → review → load_review_decisionsapply_review_decisions loop.

Behaviour changes

  • Decisions loaded from CSV have string ids; matching was already string-based.
  • New queue= parameter and new ValueError for unresolvable decisions.
  • New n_unmatched key in feedback_summary.
  • apply_review_decisions(report, []) is now an identity on clusters. Clusters it creates get ids numbered past n_records.

Tests

New tests/test_er_review_loop.py (25 test functions, 45 cases):

  • CSV round-trip with leading-zero ids; partially filled decision columns in CSV, JSONL and parquet (parquet uses importorskip("pyarrow")).
  • Round-trip for ids starting with +, -, =, @, = and \t=, including a check that the exported file is still guarded; JSONL ids and free-text notes are not stripped.
  • item_id resolution with a queue; errors without a queue, for unknown item ids and for incomplete pairs; n_unmatched; recalibration with item-id decisions.
  • Cluster identity with no decisions, redundant accept, merge, split towards and away from the canonical, no id collisions across repeated applies, and an end-to-end resolve_entities accept.

Verification

Closes #239
Closes #240
Closes #267
Closes #268

…entity

load_review_decisions (#239): CSV queues were read with type inference,
so ids such as "007" came back as 7 and never matched their pair, and a
blank decision cell became NaN -> 'nan' and raised ValueError. The CSV is
now read as text (dtype=str, keep_default_na=False); _coerce_id maps
None, NaN/pd.NA and "" to None, and blank decision cells (in any format)
are treated as undecided and skipped.

load_review_decisions (#240): the CSV export's formula sanitizer also
guards the id columns, so "+4410" is written as "'+4410" and the loaded
key never matched. On CSV load only, a leading ' is stripped from
left_id/right_id/item_id when the remainder starts with a formula prefix
(the read-only _FORMULA_PREFIXES). The export path and the sanitizer are
unchanged; JSONL/parquet ids are read verbatim because those formats are
never sanitized.

apply_review_decisions (#267): decisions carrying only an item_id were
silently dropped. A new keyword-only queue= parameter resolves item ids
through the ReviewQueueReport the reviewer worked from (item ids are
queue positions that depend on the queue config, so they are not
re-derived from the report). A decision that cannot be resolved to a
pair now raises ValueError naming it. feedback_summary gains n_unmatched,
the number of decided pairs absent from the report, and recalibration
uses the resolved decisions.

_recluster_from_pairs (#268): clusters were renumbered from er_000000
over matched records only and the canonical record reset to the lowest
id, even with no decisions. The report's clusters are now passed in: an
unchanged component keeps its cluster exactly; otherwise an original
cluster's id and canonical record follow its canonical record (a merge
keeps the lowest original id); a component with no original canonical
gets a fresh id numbered past n_records and every existing er_N id.

Closes #239
Closes #240
Closes #267
Closes #268
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 8d4d25ef-6990-4716-9ee4-93bb747ba27b


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

FreshData benchmark report — performance

  • freshdata: ?
  • python: ?
  • platform: ?
fixture n_rows n_cols p50 s p95 s peak MB repair % false-repair % preserve % trust monotonic export %

Authored-code reduction (Metric 6)

@kevincostner17
kevincostner17 merged commit 3870dee into main Sep 15, 2026
21 checks passed
kevincostner17 added a commit that referenced this pull request Sep 15, 2026
Add Unreleased Added, Changed and Fixed entries for merged PRs #351,
#352, #353, #354, #356, #357, #358, #360, #361, #362, #363, #364, #365,
#367, #368, #369, #370, #371, #372, #374, #375, #377, #378 and #379.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment