Pool admin: empty-pool safety net + honest removal copy (Codex audit)
Two hardening fixes from Codex's audit: - _pick_answer falls back to the curated baseline if the live pool is empty, so an admin tombstoning every answer in a variant can't divide-by-zero the daily picker. Test added (test_picker_survives_empty_live_pool). Chosen over a minimum-count block: robust without refusing legitimate removals. - Removal copy is now honest — "Removed from future puzzles (today's answer is already set)" — since a tombstone doesn't rewrite today's generated daily_puzzles row. Panel intro updated to match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -85,6 +85,17 @@ def test_import_dedupes_and_validates(conn):
|
||||
assert new5[1] in games.answer_pool(conn, "5")
|
||||
|
||||
|
||||
def test_picker_survives_empty_live_pool(conn):
|
||||
"""An overzealous admin could tombstone every answer in a variant. The live
|
||||
pool then reads empty, but the daily picker must not divide-by-zero — it falls
|
||||
back to the curated baseline rather than crashing."""
|
||||
for w in list(games._POOL["5"]):
|
||||
games.remove_pool_word(conn, w)
|
||||
assert games.answer_pool(conn, "5") == [] # live pool truly empty
|
||||
ans = games._pick_answer(conn, "2026-06-11", "5") # must not raise
|
||||
assert ans in set(games._POOL["5"]) # fell back to curated
|
||||
|
||||
|
||||
def test_import_relifts_removed_word(conn):
|
||||
w = _a_curated("5")
|
||||
games.remove_pool_word(conn, w)
|
||||
|
||||
Reference in New Issue
Block a user