# U7 — every falsifier the navigation unit claims, and the change it forbids. # # Generated from the session harness that proved them, not retyped. Each `old` # must match the source byte-for-byte; a drifted anchor is REPORTED, never # silently skipped — a table that stops matching stops proving anything. unit = "the rail, the filters, the grid keyboard, and the groups" [[mutation]] label = "INV-2 sort the grid by (group, rel) so groups render contiguously" file = "booth/app.py" test = "tests/test_navigation.py::test_grouping_never_reorders_the_grid" old = ''' shown = buckets[active]''' new = ''' shown = sorted(buckets[active], key=lambda i: (i["group"] or "", i["name"]))''' [[mutation]] label = "INV-3a drop the >=2 groups guard (a rail with one row)" file = "booth/app.py" test = "tests/test_navigation.py::test_no_group_rail_when_there_is_only_one_group" old = ''' if len(sizes) < 2 or sizes[len(sizes) // 2] <= 1:''' new = ''' if len(sizes) < 1 or sizes[len(sizes) // 2] <= 1:''' [[mutation]] label = "INV-3b drop the median guard (a rail that is a second copy of the grid)" file = "booth/app.py" test = "tests/test_navigation.py::test_no_group_rail_when_every_item_is_its_own_group" old = ''' if len(sizes) < 2 or sizes[len(sizes) // 2] <= 1:''' new = ''' if len(sizes) < 2:''' [[mutation]] label = "groups derived from the FULL gallery, not the rendered list" file = "booth/app.py" test = "tests/test_navigation.py::test_groups_describe_the_filtered_grid" old = ''' "groups": _groups(shown),''' new = ''' "groups": _groups(gallery),''' [[mutation]] label = "the anchor names the group key instead of the tile id" file = "booth/app.py" test = "tests/test_navigation.py::test_every_group_anchor_lands_on_a_rendered_tile" old = ''' {"key": k, "n": len(v), "anchor": f"item-{v[0]['url']}"}''' new = ''' {"key": k, "n": len(v), "anchor": f"group-{k}"}''' [[mutation]] label = "the rail orders groups alphabetically instead of by first member" file = "booth/app.py" test = "tests/test_navigation.py::test_group_order_is_the_position_of_the_first_member" old = ''' for k, v in by_group.items()''' new = ''' for k, v in sorted(by_group.items())''' [[mutation]] label = "the rail orders groups by count, which the docstring also claims differs" file = "booth/app.py" test = "tests/test_navigation.py::test_group_order_is_the_position_of_the_first_member" old = ''' for k, v in by_group.items()''' new = ''' for k, v in sorted(by_group.items(), key=lambda kv: -len(kv[1]))''' [[mutation]] label = "_group_of reverts to the contract's original strip-trailing-digits rule" file = "booth/items.py" test = "tests/test_items.py::test_group_of_takes_the_first_segment" old = ''' segs = _SEG.split(stem) if len(segs) == 1: return re.sub(r"\d+$", "", stem) or None return segs[0] or None''' new = ''' m = re.match(r"^(.*?)[-_. ]?\d+$", stem) return (m.group(1) or None) if m else (stem or None)''' [[mutation]] label = "INV-1 a route body derives the group inline" file = "booth/app.py" test = "tests/test_navigation.py::test_no_route_body_derives_a_group" old = ''' by_group: dict[str, list[dict]] = {}''' new = ''' _ = _group_of # noqa by_group: dict[str, list[dict]] = {}''' [[mutation]] label = "the rail markup is emitted with |safe" file = "booth/templates/booth.html" test = "tests/test_navigation.py::test_a_hostile_filename_cannot_break_out_of_the_rail" old = ''' href="#{{ g.anchor }}">{{ g.key }} {{ g.n }}''' new = ''' href="#{{ g.anchor }}">{{ g.key|safe }} {{ g.n }}''' [[mutation]] label = "a flat all-digit stem yields the empty string instead of None" file = "booth/items.py" test = "tests/test_navigation.py::test_a_group_key_is_never_the_empty_string" old = ''' return re.sub(r"\d+$", "", stem) or None''' new = ''' return re.sub(r"\d+$", "", stem)''' [[mutation]] label = "the template renders the group row whenever there is any group at all" file = "booth/templates/booth.html" test = "tests/test_navigation.py::test_no_group_rail_when_every_item_is_its_own_group" old = ''' {% if rail.groups %}''' new = ''' {% if rail.groups is not none %}''' [[mutation]] label = "the anchor is built from the raw name instead of the encoded url" file = "booth/app.py" test = "tests/test_navigation.py::test_a_group_anchor_survives_a_filename_that_percent_decodes" old = ''' {"key": k, "n": len(v), "anchor": f"item-{v[0]['url']}"}''' new = ''' {"key": k, "n": len(v), "anchor": f"item-{v[0]['name']}"}''' [[mutation]] label = "the anchor names the LAST member instead of the first" file = "booth/app.py" test = "tests/test_navigation.py::test_a_group_anchor_names_the_FIRST_member" old = ''' {"key": k, "n": len(v), "anchor": f"item-{v[0]['url']}"}''' new = ''' {"key": k, "n": len(v), "anchor": f"item-{v[-1]['url']}"}''' [[mutation]] label = "a group row over-reports its own size" file = "booth/app.py" test = "tests/test_navigation.py::test_a_group_row_reports_its_own_size" old = ''' {"key": k, "n": len(v), "anchor": f"item-{v[0]['url']}"}''' new = ''' {"key": k, "n": len(v) + 1, "anchor": f"item-{v[0]['url']}"}''' [[mutation]] label = "the informativeness guard reads the LARGEST group, not the middle" file = "booth/app.py" test = "tests/test_navigation.py::test_the_informativeness_guard_reads_the_middle_not_the_largest" old = ''' if len(sizes) < 2 or sizes[len(sizes) // 2] <= 1:''' new = ''' if len(sizes) < 2 or sizes[-1] <= 1:''' [[mutation]] label = "the rail is gated on the FILTERED list, removing the way back" file = "booth/templates/booth.html" test = "tests/test_navigation.py::test_a_filter_that_matches_nothing_leaves_a_way_back" old = ''' {% elif all_items %}''' new = ''' {% elif items %}''' [[mutation]] label = "the keyboard flag selector names a class nothing emits" file = "booth/templates/booth.html" test = "tests/test_navigation.py::test_the_keyboard_flag_targets_a_real_button" old = ''' case 'f': click('.flagtoggle button');''' new = ''' case 'f': click('.flagbtn, [name="target"]');''' [[mutation]] label = "an unrepresentable filename is let through and 500s the booth" file = "booth/items.py" test = "tests/test_items.py::test_one_unrepresentable_filename_costs_its_own_tile_not_the_booth" old = ''' try: quote(rel, safe="/") except UnicodeEncodeError:''' new = ''' try: pass except UnicodeEncodeError:''' [[mutation]] label = "the grid cursor starts at tile 0, so an arrow undoes a group jump" file = "booth/templates/booth.html" test = "tests/test_embed_browser.py::test_an_arrow_after_a_group_jump_does_not_scroll_back" old = ''' case 'ArrowRight': focus(at < 0 ? fromViewport() : at + 1);''' new = ''' case 'ArrowRight': focus(at + 1);''' [[mutation]] label = "the link board drops its href scheme guard" file = "booth/links.py" test = "tests/test_booth.py::test_the_link_board_refuses_to_render_a_script_href" old = ''' return parts.scheme.lower() in ("http", "https")''' new = ''' return True''' [[mutation]] label = "the board delete dialog takes the raw agent-written description" file = "booth/templates/booth.html" test = "tests/test_booth.py::test_the_board_delete_dialog_cannot_be_rewritten_by_a_link_row" old = ''' var d = shown(btn.getAttribute('data-desc') || '');''' new = ''' var d = btn.getAttribute('data-desc') || '';'''