S6. The sender's latest position (airplanes, path, test) and the repeater-or-room-server lookup by name (prefix, solarforecast) were each pasted into the commands, alongside location.py's own copies for get_companion_lat_lon and lookup_repeater_lat_lon. They now run through location.latest_contact_position_rows and location.repeater_by_name_rows. The copies differed only in how they drop a zero coordinate, so that is a zero_rule parameter: "both" (location.py's helpers: drop only 0,0) or "either" (the commands: drop a fix with either coordinate zero), and each caller passes the rule it had. Each command keeps its private wrapper, its pubkey access, try/except, log text and value conversion; airplanes' _get_bot_location now calls get_bot_lat_lon, which is the same code.
I did not move the commands onto resolve_location: its labels and geocoding rules differ from what each command does today. Old-vs-new over 20,000 randomized cases against a real SQLite table (zero coordinates, ties, near-duplicate names, missing pubkeys, database errors, no db_manager) matched on results and log calls for all eight functions; four mutations were each caught.