Off-BGG games become local library citizens
An unmatched title that's a REAL game BGG doesn't have dead-ended: manual id or reject. The RPG local-citizen pattern generalizes to a human decision — review (web + TUI, key l) gains "not on BGG — keep locally": match_status "local" clears any BGG identity, diff routes it to local_only (never queued), and enrich synthesizes a library entry from the game's own photo reads (name, year, publisher cue — no API call, so even a blocked run lands them; pruning keeps local keys). Library and Titles show a "local — not on BGG" chip; Help's legend, review description, and shortcuts cover the new verb, distinguishing it from reject (bad read / not a game). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
This commit is contained in:
co-authored by
Claude Fable 5
parent
59f4b8c43c
commit
e187ed4f3f
@@ -226,3 +226,55 @@ def test_enrich_degrades_without_token(tmp_path, capsys):
|
||||
assert games == {}
|
||||
assert "waiting on the BGG API" in capsys.readouterr().out
|
||||
assert json.loads((cfg.data_dir / "games.json").read_text()) == {}
|
||||
|
||||
|
||||
def test_local_rows_enrich_from_their_own_reads(tmp_path):
|
||||
cfg = Config(data_dir=tmp_path / "data")
|
||||
cfg.data_dir.mkdir(parents=True)
|
||||
write_matches(
|
||||
cfg.matches_path,
|
||||
[
|
||||
{
|
||||
"title_raw": "Obscure Homebrew",
|
||||
"bgg_id": "",
|
||||
"bgg_name": "",
|
||||
"year": "",
|
||||
"type": "",
|
||||
"match_status": "local",
|
||||
"version_id": "",
|
||||
"version_name": "",
|
||||
"version_status": "",
|
||||
"candidates_json": "[]",
|
||||
"version_candidates_json": "[]",
|
||||
"source_photos": "shelf.jpg",
|
||||
}
|
||||
],
|
||||
)
|
||||
cfg.titles_path.write_text(
|
||||
json.dumps(
|
||||
[
|
||||
{
|
||||
"title_raw": "Obscure Homebrew",
|
||||
"publisher_hint": "Basement Press",
|
||||
"year_hint": 1998,
|
||||
"source_photos": ["shelf.jpg"],
|
||||
}
|
||||
]
|
||||
)
|
||||
)
|
||||
from bggpipe.enrich import run_enrich
|
||||
|
||||
client = BGGClient(
|
||||
cache_dir=cfg.data_dir / "cache",
|
||||
transport=httpx.MockTransport(_no_network),
|
||||
)
|
||||
games = run_enrich(cfg, client=client)
|
||||
(key,) = [k for k in games if k.startswith("local:")]
|
||||
entry = games[key]
|
||||
assert entry["name"] == "Obscure Homebrew"
|
||||
assert entry["year"] == 1998
|
||||
assert entry["publishers"] == ["Basement Press"]
|
||||
assert entry["type"] == "localgame"
|
||||
# idempotent: a second run keeps the entry (no prune, no dupe)
|
||||
games2 = run_enrich(cfg, client=client)
|
||||
assert key in games2
|
||||
|
||||
Reference in New Issue
Block a user