Status: ready-for-agent

Scoped 2026-07-07 from an interrupted Claude session. This is a resume/cleanup task for routing and live-progress work that is partly committed and partly left dirty in the working tree.

# 24 - Finish learned-routing telemetry and live-progress cleanup

## Current state

The main dynamic routing feature is already committed at `518c259` (`routing improvements - dynamic (wip)`):

- `packages/tracker/meshnet_tracker/routing_stats.py` - decayed-EWMA route stats store, epsilon-greedy route selection, diagnostics.
- `packages/tracker/meshnet_tracker/server.py` - route enumeration per head, bandit selection in the chat proxy, epoch bumps on node join/leave, `/v1/routing`, route sample recording with 8-token hygiene.
- `packages/tracker/meshnet_tracker/cli.py` - `--route-explore-share`, `--route-weight-alpha`, `--route-stats-half-life` and env vars.
- `packages/tracker/meshnet_tracker/dashboard.html` - "Routing (learned)" panel.
- `docs/adr/0021-dynamic-statistical-routing.md` - design record.
- `tests/test_dynamic_routing.py` - includes the exact GPU(0-21)+CPU(0-39) topology, hybrid downstream `start_layer=22`, 0.6/0.4 traffic split for a 1.5 TPS ratio, and scout-rate behavior.

The current working tree still has uncommitted follow-up work:

- `packages/node/meshnet_node/torch_server.py` - tracks in-flight chat requests, exposes `TorchNodeServer.current_requests`, prints generation progress with TPS.
- `packages/node/meshnet_node/startup.py` - sends `current_requests` in heartbeat payloads and increases heartbeat cadence while busy.
- `packages/tracker/meshnet_tracker/server.py` - accepts heartbeat `current_requests`, includes them in `/v1/network/map`, and logs `proxy connecting` before upstream connection.
- `packages/tracker/meshnet_tracker/dashboard.html` - enriches the call wall from heartbeat `current_requests` so active requests remain visible even before terminal proxy events.
- `tests/test_real_model_backend.py` and `tests/test_tracker_routing.py` - targeted coverage for current-request snapshots, heartbeat sanitization/storage, and TPS progress logging.
- `QUICKSTART.md` - documents optional linear-attention fast-path packages for Qwen3.5/3.6 GPU nodes.

There is also an untracked local file, `.claude/settings.local.json`, which should not be included unless the owner explicitly wants local Claude settings committed.

## Known blocker found during resume

Targeted pytest currently fails during import before reaching the new tests:

```text
TypeError: unsupported operand type(s) for |: 'builtin_function_or_method' and 'NoneType'
```

Immediate cause: `packages/tracker/meshnet_tracker/server.py:1490` annotates `ws_lock: threading.Lock | None = None`. `threading.Lock` is a factory function at runtime, not a type, so `| None` evaluates eagerly and crashes. This exists on `HEAD` too, not just in the dirty telemetry changes.

Fix options:

- Add `from __future__ import annotations` at the top of `server.py`, then run enough tests to catch any annotation side effects.
- Or change that annotation to a safe runtime type such as `Any | None` / remove the union annotation. Keep the change minimal.

## What to do next

1. Fix the import-time `threading.Lock | None` crash.
2. Re-run the targeted tests:

   ```bash
   .\.venv\Scripts\python.exe -m pytest tests/test_tracker_routing.py::test_tracker_heartbeat_stores_current_requests tests/test_tracker_routing.py::test_normalize_current_requests_sanitizes_payload tests/test_real_model_backend.py::test_current_requests_snapshot_while_generating tests/test_real_model_backend.py::test_distributed_generating_log_includes_tps -q
   ```

3. Run the relevant routing regression tests:

   ```bash
   .\.venv\Scripts\python.exe -m pytest tests/test_dynamic_routing.py tests/test_tracker_routing.py -q
   ```

4. If practical, run the non-integration suite:

   ```bash
   .\.venv\Scripts\python.exe -m pytest tests/ -q -m "not integration"
   ```

5. Confirm or document the pre-existing failure from the interrupted session: `test_proxy_chat_splits_payout_by_tracker_assigned_route_span` reportedly failed on `HEAD` too and was unrelated.
6. Commit the intentional work in two commits if it remains naturally split:
   - learned routing is already committed in `518c259`; leave it alone unless fixing regressions there.
   - commit the live-progress/current-request telemetry cleanup separately after tests pass.

## Acceptance criteria

- [ ] Importing `meshnet_tracker.server` no longer crashes on the lock annotation.
- [ ] Current-request heartbeat payloads are sanitized and surfaced in `/v1/network/map`.
- [ ] Node-side in-flight chat snapshots report request id, model, token count, elapsed seconds, tokens/sec, and routing completion.
- [ ] Dashboard call wall can show active requests from heartbeat data, not only tracker console terminal events.
- [ ] Targeted telemetry tests pass.
- [ ] Dynamic routing tests still pass, including GPU(0-21)+CPU(0-39) hybrid-route enumeration and traffic split behavior.
- [ ] Full or non-integration suite result is recorded; unrelated pre-existing failures are named explicitly.
- [ ] `.claude/settings.local.json` remains uncommitted unless intentionally approved.

## ADR links

- [ADR-0020](../../docs/adr/0020-chat-streaming-live-progress-and-mixed-topology-routing.md)
- [ADR-0021](../../docs/adr/0021-dynamic-statistical-routing.md)

## Blocked by

None. The import-time annotation crash is the first fix.

## Blocks

Clean handoff/commit of the interrupted live routing progress work.
