Re-audit round 3: 5 blind reviewers, 15 fixes, +18 tests — converging
Round 3's two HIGHs: _fill_version resolved versions with the LAST same-title entry's cues (photo-aware lookup existed since round 1 but this caller never used it), and the round-2 diff rework let an earlier row's disagreement consume the exact-version copy a later row matched. Diff claims now settle strongest-first across all rows (exact matches, then versionless upgrades, then disagreement/second-copy), unvetoed bare duplicates stay owned per spec, and updates are withheld with a manual-fix note whenever any copy of the game already carries a version (the row edit targets by name and could hit the wrong copy). Also: entry-to-row pairing matches by photo overlap before position (titles.json order churn from reshoot filenames could swap editions); BGGQueueTimeout defers a title like a missing token; DismissStore writes atomically, mutates memory only after the write, and quarantines a torn file instead of bricking the server; version-picker page-limit exhaustion stays retryable; verify's copy-count shortfall reports once per game (the old guard was dead code); the upload log header is created atomically; transient version-lookup failures record a retryable version_error, not terminal version_unknown; extract isolates per-photo failures and salvages JSON followed by prose; a state revision counter stops stale poll responses reverting decisions; plus the shared-predicate/fsio/docstring consolidation and CLI wiring, live-diff, verify-wiring, and search-guard tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -631,3 +631,36 @@ def test_truncation_separator_chosen_by_position():
|
||||
heads = _truncation_heads("Blorvath: Quest of the Zzyzx - 2nd Edition")
|
||||
assert heads[0] == "Blorvath"
|
||||
assert "Blorvath: Quest" not in heads # the comment's guarantee, now true
|
||||
|
||||
|
||||
def test_reordered_titles_json_cannot_mispair_editions(client, tmp_path):
|
||||
# run 1 resolves "Catan" from b.jpg; run 2 prepends a NEW conflicting-cue
|
||||
# "Catan" sighting from a.jpg (sorts earlier). Photo-overlap pairing must
|
||||
# keep the b.jpg row glued to the b.jpg entry — not hand its resolution
|
||||
# (and photos) to the newcomer positionally.
|
||||
data_dir = tmp_path / "data"
|
||||
data_dir.mkdir()
|
||||
entry_b = {
|
||||
"title_raw": "Catan",
|
||||
"language_hint": "English", # conflicts with a.jpg's German; language
|
||||
"source_photos": ["b.jpg"], # alone never triggers a versions fetch
|
||||
}
|
||||
(data_dir / "titles.json").write_text(json.dumps([entry_b]))
|
||||
cfg = Config(data_dir=data_dir)
|
||||
run_resolve(cfg, client=client)
|
||||
(row,) = read_matches(cfg.matches_path)
|
||||
assert row["source_photos"] == "b.jpg"
|
||||
|
||||
entry_a = {
|
||||
"title_raw": "Catan",
|
||||
"language_hint": "German",
|
||||
"source_photos": ["a.jpg"],
|
||||
}
|
||||
(data_dir / "titles.json").write_text(json.dumps([entry_a, entry_b]))
|
||||
run_resolve(cfg, client=client)
|
||||
|
||||
rows = read_matches(cfg.matches_path)
|
||||
by_photos = {r["source_photos"]: r for r in rows}
|
||||
assert by_photos["b.jpg"]["match_status"] == "auto" # kept its resolution
|
||||
assert "a.jpg" in by_photos # newcomer resolved as its own row
|
||||
assert len(rows) == 2
|
||||
|
||||
Reference in New Issue
Block a user