Shaky reads become visible and clearable on the Titles page

The badge counted lines nothing on the page identified. Each shaky line
(vision confidence below high, nothing verified yet — the badge's exact
predicate, served per-line so page and badge can't disagree) now shows
a dashed gold "shaky read" chip, a filterbar toggle shows just them,
and a "✓ looks right" button confirms a correct read in one click —
recorded as a confidence-high edit record, so verification is as
durable as any other curation and, unlike a real edit, re-queues
nothing. Saving an unchanged edit form on a shaky line counts as
confirming it. Help's chip legend explains the chip and its three ways
to clear (confirm, edit, or a BGG match).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
This commit is contained in:
Eric Wagoner
2026-08-03 00:25:48 -04:00
parent f19b861251
commit 1d700db012
5 changed files with 106 additions and 13 deletions
+46
View File
@@ -823,3 +823,49 @@ def test_nav_order_matches_workflow(tmp_path):
assert order == sorted(order)
# the old address still lands on the page
assert web.get("/catalog", follow_redirects=False).headers["location"] == "/titles"
def test_confirm_marks_shaky_read_verified_without_requeue(tmp_path):
cfg = make_cfg(tmp_path)
titles = json.loads(cfg.titles_path.read_text())
titles.append(
{
"title_raw": "Blurry Spine",
"confidence": "low",
"source_photos": ["shelf.jpg"],
}
)
cfg.titles_path.write_text(json.dumps(titles))
web = TestClient(create_app(cfg, client=unauthorized_client(tmp_path)))
line = next(
c
for c in web.get("/api/state").json()["catalog"]
if c["title_raw"] == "Blurry Spine"
)
assert line["shaky"] is True
rows_before = read_matches(cfg.matches_path)
res = web.post(
"/api/edit-title",
json={
"title_raw": "Blurry Spine",
"source_photos": "shelf.jpg",
"confirm": True,
},
)
assert res.status_code == 200
line = next(c for c in res.json()["catalog"] if c["title_raw"] == "Blurry Spine")
assert line["shaky"] is False # verified: chip and badge both clear
assert web.get("/api/pipeline").json()["shaky_reads"] == 0
# confirm changed no data, so nothing was re-queued
assert read_matches(cfg.matches_path) == rows_before
(record,) = json.loads(cfg.title_edits_path.read_text())
assert record["confidence"] == "high"
# a change-free save without confirm is still refused
assert (
web.post(
"/api/edit-title",
json={"title_raw": "Blurry Spine", "source_photos": "shelf.jpg"},
).status_code
== 400
)