From 3b3a78820aefb9c099dab8e945e2daaf614e434c Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sun, 30 Aug 2026 22:41:42 +0200 Subject: [PATCH] fix: the tagger pre-selected a group, which is how an album reaches the wrong chat The first group in the account's listing was checked by default, and the first group in this account's listing is a test group. Somebody who typed the names, hit save and never looked at the radios would have scoped a private album to the wrong chat -- silently, because the commands then simply do nothing in the chat they were meant for. Nothing is pre-selected now, and saving without a group is refused. Also replaces a test of mine that failed one run in sixteen: it drew a two-way random choice five times and demanded both outcomes. The property worth pinning is that a choice lands on a reading that *has* photos, which is deterministic when only one of them does. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_017w1HZ3cZ7neL3rFdQ6VMBA --- tests/test_pack_command.py | 22 +++++++++++++++++----- tool/tagger.html | 10 ++++++---- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tests/test_pack_command.py b/tests/test_pack_command.py index f6752e2..1e413c6 100644 --- a/tests/test_pack_command.py +++ b/tests/test_pack_command.py @@ -136,13 +136,25 @@ async def test_a_name_nobody_has_gets_the_same_answer( async def test_a_choice_lands_on_the_reading_that_has_a_photo( tmp_path: Path, transport: FakeTransport, store: Store, config: Config ) -> None: - """p2 has no photo of their own, so "either of them" must not fail.""" - pack = load( - pack_fixture.build(tmp_path / "pack", tags={"gamma.png": ["p3"], "both.png": ["p1", "p2"]}) - ) + """p2 has no photo at all, so "either of them" must land on p3 every time. + + Deterministic on purpose. Asserting that a random choice eventually + produces both readings is a test that fails one run in sixteen, and this + repo has already shipped one bug because a random API was believed after + a single call. + """ + pack = load(pack_fixture.build(tmp_path / "pack", tags={"gamma.png": ["p3"]})) for _ in range(5): await _run(pack, transport, store, config, "!ktokolwiek") - assert {message.filename for message in transport.sent} == {"gamma.png", "both.png"} + assert [message.filename for message in transport.sent] == ["gamma.png"] * 5 + + +async def test_a_choice_with_nothing_behind_either_reading_is_answered( + tmp_path: Path, transport: FakeTransport, store: Store, config: Config +) -> None: + pack = load(pack_fixture.build(tmp_path / "pack", tags={"alfa.png": ["p1"]})) + await _run(pack, transport, store, config, "!ktokolwiek") + assert transport.texts == [NO_PHOTO] async def test_a_video_keeps_being_a_video( diff --git a/tool/tagger.html b/tool/tagger.html index d1ea1bd..9c30526 100644 --- a/tool/tagger.html +++ b/tool/tagger.html @@ -76,8 +76,6 @@ const api = (path, body) => fetch(path, body ? { let state = null; let at = 0; -function key(name, index) { return name || `p${index + 1}`; } - function parseSetup(text) { const people = [], combos = []; const byName = new Map(); @@ -110,8 +108,11 @@ function drawGroups(known, chosen) { box.innerHTML = ''; return; } - box.innerHTML = known.map((g, i) => `