Skip to content

Delete the modules, endpoints and aliases nothing calls - #437

Merged
Babissimo merged 1 commit into
mainfrom
chore/delete-dead-modules
Sep 17, 2026
Merged

Babissimo merged 1 commit into
mainfrom
chore/delete-dead-modules

Conversation

@Babissimo

Copy link
Copy Markdown
Contributor

Closes the first tranche-2 item of the consolidation survey: 123zgec37j1.

267 lines net, all of it removal. Each item was verified caller-free by enumerating references across every repo under the workspace, on all branches and including gitignored directories, rather than by reading the code that defines it.

Deleted outright

What Why it is dead
services/background.py A re-export shim; services/tasks/__init__.py already exports the same sixteen names, and no test imported the old path. main.py now imports the package.
core/types.py Four TypedDicts, zero importers. NodeState also shadowed an unrelated NodeState in routes/node_schemas.py.
scripts/smoke_parquet_archive.py Both behaviours covered by test_parquet_writer.py and test_storage.py.
/api/test/anomalies Superseded by /api/radar/anomalies, which is what the dashboard calls. The test version dumped anomaly_log raw and unauthenticated where the radar one redacts, and read both anomaly_log and anomaly_hexes without taking state.anomaly_lock, which the radar one does.
Two _get_stale_tasks aliases Left behind when the duplicated rule was collapsed into core/task_registry.

Deleted after confirming with the ticket owner

/api/radar/load-file and pipeline.passive_radar's batch __main__ were the two entry points to the offline .detection path. Nothing under the workspace reaches either: no runbook, justfile recipe, deploy script, compose command or CI step. load-file was also the only path-traversal-validating file reader in the tree, so it was security surface being maintained for no traffic.

Those two were the only callers of PassiveRadarPipeline.process_file, so it goes with them and the batch .detection path leaves the codebase entirely. The live geolocation path is _run_geolocation driven by the frame loop, untouched and well covered. generate_aircraft_json stays, still pinned by test_pipeline.py, though it now has no production caller: its tar1090 batch schema was already superseded by the flush task's, as the deleted handler's own comment described.

What was kept, and what turned out to be wrong

core/types.py's descriptions outlived the file, but checking them against the code before rehoming them showed two of the four had drifted. Both were about to be copied into core/state.py, where sitting beside the store they describe would make them far more likely to be believed than they were in a module nothing imported:

  • AircraftPosition listed callsign, seen, squawk, rssi and node_id. services/tcp_handler.py:611 actually builds flight, last_seen_ms, recv_ms and world, then extends the record via adsb_derived_fields. The TypedDict omitted last_seen_ms entirely — the field feed_helpers.adsb_store orders writes on and feed_gc evicts on.
  • NodeState gave status as "active" | "disconnected". _handle_heartbeat does hb_status = msg.get("status", "active") and assigns it verbatim, so any string a node reports lands there; routes/node_schemas.py:109 defines six more that nodes plausibly send.

So connected_nodes and adsb_aircraft carry corrected comments rather than copies, and the adsb_aircraft one names its writer instead of restating a field list that had already drifted once. Nothing branches on either description today, so no live fault is fixed here.

TaskHealth was already stated verbatim beside task_last_success and task_error_counts, and GeoAircraft describes a payload one readable function builds, so neither was carried across.

Verification

  • pre-commit run --all-files clean, vulture included: removing the whitelist block for core/types.py left nothing newly flagged.
  • Backend suite green (test_mlat_history.py deselected locally for its runtime; CI runs it).
  • python -m scripts.generate_openapi --check reports the node contract current, as expected since neither removed route sits under /v1/nodes.
  • Removing the handler left Depends and require_admin unused in routes/radar.py, confirming it was that module's only admin-gated route.

Also confirmed stale and closeable: 86cb7v7hd asks for backend/scripts/retnode_poller.py, deleted by de65050a and merged in #344.

🤖 Generated with Claude Code

Seven pieces of the backend had no callers left. Each was verified by
enumerating references across every repo under the workspace, on all
branches, rather than by reading the code that defines them:

  - services/background.py, a re-export shim whose docstring says it
    exists so main.py and tests keep importing the old path. No test
    imported it and services/tasks/__init__.py already exported the
    same sixteen names, so main.py now imports the package directly.
  - core/types.py, four TypedDicts with zero importers, justified in
    the vulture whitelist as "used as type annotations" when they are
    not. NodeState also shadowed an unrelated NodeState in
    routes/node_schemas.py.
  - scripts/smoke_parquet_archive.py, whose two behaviours are covered
    by test_parquet_writer.py and test_storage.py.
  - /api/test/anomalies, superseded by /api/radar/anomalies, which the
    dashboard actually calls. The test version dumped anomaly_log raw
    and unauthenticated where the radar one redacts, so this also
    closes a small disclosure.
  - the two _get_stale_tasks aliases, left behind when the duplicated
    rule was collapsed into core/task_registry.
  - /api/radar/load-file and pipeline.passive_radar's batch __main__,
    the two entry points to the offline .detection path. Neither is
    reachable from a runbook, justfile recipe, deploy script or CI
    step. load-file was also the codebase's only path-traversal check,
    security surface maintained for no traffic.

Deleting those last two orphaned PassiveRadarPipeline.process_file,
their only caller, so it goes with them and the batch .detection path
leaves the tree entirely. The live geolocation path is _run_geolocation
driven by the frame loop, which is untouched and well covered.
generate_aircraft_json stays: its tar1090 batch schema is superseded by
the flush task's, but test_pipeline.py still pins it.

core/types.py's descriptions were worth keeping, but not verbatim:
checked against the code, two of the four had drifted. AircraftPosition
listed callsign, seen, squawk and rssi, where tcp_handler builds flight,
last_seen_ms, recv_ms and world, and omitted last_seen_ms altogether —
the field adsb_store orders writes on and feed_gc evicts on. NodeState
gave status as "active" | "disconnected", but _handle_heartbeat assigns
msg.get("status") straight from the wire, so it is not a closed set.

connected_nodes and adsb_aircraft therefore carry corrected comments
rather than copies, and the adsb one names its writer instead of
restating a field list that had already drifted once. TaskHealth was
already stated verbatim beside task_last_success and task_error_counts,
and GeoAircraft describes a payload one readable function builds, so
neither was carried across.

Nothing branches on either description today, so this fixes no live
fault; it stops the file's claims being re-inherited as fact.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@claude

claude Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

Claude finished @Babissimo's task in 2m 7s —— View job


Review complete

  • Gather context (read PR diff, CLAUDE.md/ONBOARDING.md)
  • Review deleted modules for remaining references
  • Review route/handler removals (/api/test/anomalies, /api/radar/load-file)
  • Review core/types.py deletion and comment rehoming in core/state.py
  • Review vulture whitelist / pyproject changes

Looked at the full diff (git diff feabebe~1..feabebe) plus a repo-wide grep for every removed symbol (load-file, process_file, smoke_parquet_archive, services.background, core.types, _get_stale_tasks, /api/test/anomalies) across all file types, not just backend/. No leftover references anywhere.

Findings: none. This is a well-executed dead-code removal:

  • services/background.py → services/tasks: main.py's import block now points at services.tasks directly (backend/main.py diff), and the package docstring in backend/services/tasks/__init__.py was updated to stop describing itself as a shim for a file that no longer exists.
  • Two _get_stale_tasks aliases: confirmed core/task_registry.get_stale_tasks is the real definition (backend/core/task_registry.py:39), and both call sites (routes/admin.py, routes/test.py) now call it directly. The test file was updated to import from the real module too.
  • /api/radar/load-file removal: checking routes/radar.py, removing the handler correctly took Depends/require_admin/LoadFileRequest/_ALLOWED_DETECTION_DIR with it — I verified none of those are referenced elsewhere in the file, and Header (still used by two other routes) was correctly left in the import.
  • /api/test/anomalies removal: Response/orjson imports in routes/test.py are both still used by many other handlers in that file, so nothing over-pruned there.
  • pipeline.passive_radar batch path removal: process_file, process_detection_folder, and the __main__ block are gone along with their now-unused glob/json imports. generate_aircraft_json correctly stays — it's still exercised by test_pipeline.py:282-284 even though its only production caller is gone.
  • core/types.py deletion: the PR's own account of why it's safe to delete without literally copying the TypedDict field lists checks out. Spot-checking AircraftPosition against services/tcp_handler.py:611 and the new comment in backend/core/state.py, the old TypedDict was in fact missing last_seen_ms/recv_ms and had fields (callsign, seen, squawk, rssi, node_id) that don't match what's actually built. The replacement comments in core/state.py describe the writer/invariant instead of restating a field list, which is the right call given the drift found. vulture_whitelist.py and pyproject.toml's coverage omit list were cleaned up in step with the deletion.

Nice attention to detail overall — deleting core/types.py outright rather than quietly keeping stale documentation around, and using the ticket owner's confirmation for the two entry-point deletions rather than assuming, are both good calls.

@Babissimo
Babissimo merged commit ae803af into main Sep 17, 2026
15 checks passed
@Babissimo
Babissimo deleted the chore/delete-dead-modules branch September 21, 2026 08:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant