# R2 — the review flow: falsifiers the round claims, and the change each forbids. # # Every row was proved RED under its mutation in the session that wrote it, # then committed here so the proof is an artifact rather than scrollback. The # browser rows need the Playwright Chromium the browser tests already use. # # Deliberately ABSENT: single guards inside a defence in depth, each of which # stays green when removed alone because another layer still holds — so a row # for any one of them would be a vacuous proof, and this table's own first run # said so. `.seen`'s O_NOFOLLOW, O_NONBLOCK and S_ISREG (the FIFO/symlink test # covers them together); and `flagged_targets`' `error is None`, since # hydration already strips the target from a damaged mark. # # The serialization row is only a falsifier because its test HOLDS the first # refresh in the client: localhost alone never lost the race, and the first # draft of that test stayed green with serialization deleted. unit = "the Desk, the lightbox, the review, and the in-place client" [[mutation]] label = 'C1 ordinals count from 0, not 1' file = "booth/items.py" test = "tests/test_flow.py::test_a_filtered_tile_keeps_its_number_in_the_whole_set" old = '''ordinal=len(items) + 1,''' new = '''ordinal=len(items),''' [[mutation]] label = 'C2 .seen: a nested-too-deep marker escapes the never-raises read' file = "booth/items.py" test = "tests/test_flow.py::test_a_deeply_nested_seen_marker_reads_as_nothing_seen" old = '''except (UnicodeDecodeError, ValueError, RecursionError):''' new = '''except (UnicodeDecodeError, ValueError):''' [[mutation]] label = 'C3 a non-finite q is accepted as a q-value' file = "booth/app.py" test = "tests/test_flow.py::test_a_non_finite_q_is_malformed" old = ''' raise ValueError("non-finite q")''' new = ''' pass''' [[mutation]] label = 'C3 204 on an explicit JSON Accept becomes the 303' file = "booth/app.py" test = "tests/test_flow.py::test_an_explicit_json_accept_gets_204_and_the_write_still_lands" old = ''' return Response(status_code=204)''' new = ''' pass''' [[mutation]] label = 'C3 back=view lands on the review for a doc too (ring check dropped)' file = "booth/app.py" test = "tests/test_flow.py::test_back_view_lands_on_the_review_only_for_a_media_item" old = ''' if f in ring:''' new = ''' if True:''' [[mutation]] label = 'C4 the Desk counts orphan flags' file = "booth/app.py" test = "tests/test_flow.py::test_a_flag_on_a_file_that_is_gone_stays_visible_and_withdrawable" old = '''"flags": len(flagged_targets(marks) & {it.rel for it in items}),''' new = '''"flags": len(flagged_targets(marks)),''' [[mutation]] label = 'C4 landed_at follows symlinks' file = "booth/app.py" test = "tests/test_flow.py::test_the_content_clock_reads_the_booth_not_what_its_links_point_at" old = ''' st = p.lstat()''' new = ''' st = p.stat()''' [[mutation]] label = 'C4 one unreadable entry reads the whole booth as landed NOW' file = "booth/app.py" test = "tests/test_flow.py::test_one_unreadable_entry_costs_that_entry_not_the_booth" old = '''pin it in "new" forever. continue''' new = '''pin it in "new" forever. return time.time()''' [[mutation]] label = 'C4 a non-web bookmark URL becomes a link' file = "booth/templates/index.html" test = "tests/test_flow.py::test_the_desk_never_makes_a_non_web_url_clickable" old = '''{% set web = e.url.lower().startswith(('http://', 'https://')) %}''' new = '''{% set web = true %}''' [[mutation]] label = 'C4 a non-web bench URL becomes a link' file = "booth/templates/index.html" test = "tests/test_flow.py::test_the_desk_never_makes_a_non_web_url_clickable" old = '''{% set web = b.url.lower().startswith(('http://', 'https://')) %}''' new = '''{% set web = true %}''' [[mutation]] label = 'C5 audio/video tiles lose their review link' file = "booth/templates/booth.html" test = "tests/test_flow.py::test_a_sound_only_booth_can_open_the_review" old = '''{% if it.kind in ('video', 'audio') %}''' new = '''
''' [[mutation]] label = "C6 the next arrow's rail offset applies at phone width" file = "booth/templates/view.html" test = "tests/test_flow_browser.py::test_the_next_arrow_clears_the_rail_only_beside_it" old = ''' .vprev{left:0}.vnext{right:0} @media (min-width:901px){.vnext{right:360px}} ''' new = ''' .vprev{left:0}.vnext{right:360px} ''' [[mutation]] label = "resolver: an entry that cannot be stat'd raises out of booth_items" file = "booth/items.py" test = "tests/test_items.py::test_a_folder_that_lists_but_cannot_be_searched_costs_its_files_not_the_index" old = ''' if not p.is_file(): continue except OSError: continue''' new = ''' if not p.is_file(): continue except FileNotFoundError: continue''' [[mutation]] label = "Desk row controls hidden until hover again (opacity 0 keeps their box)" file = "booth/templates/base.html" test = "tests/test_flow_browser.py::test_a_rows_keep_release_and_wipe_take_no_room_of_their_own" old = ''' .desk-facts form{display:inline;margin:0}''' new = ''' .desk-facts form{display:inline;margin:0;opacity:0}''' [[mutation]] label = "Desk row renders its side column with no badge in it (a reserved gap)" file = "booth/templates/index.html" test = "tests/test_flow_browser.py::test_a_rows_keep_release_and_wipe_take_no_room_of_their_own" old = ''' {% if b.marks_open or b.hold == "unreadable" or section == 'new' or b.uploaded %}
''' new = ''' {% if true %}
''' [[mutation]] label = "the stacked Desk column is a bare 1fr (content sets its minimum)" file = "booth/templates/base.html" test = "tests/test_flow_browser.py::test_the_desk_never_scrolls_sideways_on_a_phone" old = ''' @media (max-width:1000px){.desk{grid-template-columns:minmax(0,1fr)}}''' new = ''' @media (max-width:1000px){.desk{grid-template-columns:1fr}}'''