Files
echolot/CLAUDE.md
T
mrambossekandClaude Opus 5 9d4b41da7f
server-release / release (push) Failing after 41s
CLAUDE.md: device-testing lessons for future sessions; ignore web/.wrangler
The wireless-adb findings, report-collection workflow, build-number
convention, per-device Shizuku matrix, and the JDK constraint now live in
the repo so a session on any machine starts with them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 15:43:32 +02:00

4.7 KiB
Raw Blame History

Echolot — context for Claude Code

This repo is the capability prober for the Echolot project: an F/OSS Android app for detecting and debugging local network issues (target audience: network engineers). The prober validates the no-root feasibility matrix on real hardware before the production app is built.

Project facts

  • Name: Echolot. Domain echo-lot.app. URI scheme echolot://. Namespace app.echo_lot.* (hyphen→underscore; appIds/packages can't contain hyphens). Prober appId: app.echo_lot.prober.
  • Stack: native Kotlin + Jetpack Compose. No Flutter (all value is in platform APIs; Flutter would be a Dart skin over a full Kotlin app + F-Droid build friction).
  • Tiers: app (no root), shizuku (ADB-shell privileges via wireless pairing, shipped in v1), root (future module). Every result records which tier produced it.
  • License: code is GPL-3.0-or-later (LICENSE), the specs in docs/ are CC-BY-4.0 (docs/LICENSE). New source files get the two-line SPDX header the existing ones carry. The server, when it lands, is GPL too — not AGPL (see docs/build-status.md for the reasoning).

Design docs (source of truth, in docs/)

  • docs/feature-catalog-and-feasibility.md — full feature list + no-root feasibility matrix.
  • docs/measurement-schema.md — the archived/exportable measurement JSON format (observation vs finding separation, two-clock rule, columnar trains, anonymization types).
  • docs/probe-protocol.md — client↔server wire protocol (pinned-TLS control plane, binary UDP data plane with anti-amplification HMAC, STUN, canary DNS reference records).
  • docs/build-status.md — running log of decisions, what is delivered, and the next steps.

The three specs are draft-complete and user-reviewed; treat them as the contract. build-status.md is the mutable one — update it as work lands.

Keep prober result IDs aligned with the measurement-schema test-type registry.

Layout

Monorepo. The prober is one deliverable; the Go server and the production app land as siblings.

docs/                          design docs (above) — apply repo-wide, not just to the prober
echolot-prober/                the capability prober (self-contained Gradle build)
  app/src/main/java/app/echo_lot/prober/
    MainActivity.kt            Compose host, runs probes sequentially
    probe/                     Probe interface + all app-tier probes + OS ABI helper
    shizuku/                   AIDL UserService + ShizukuRunner (shell command exec)
    export/Report.kt           JSON report + share intent
    ui/ProberScreen.kt         result cards colored by verdict

Conventions

  • Every probe returns a ProbeResult — never throws to the caller (MainActivity wraps anyway).
  • Uncertain OS API paths (getsockoptInt, recvmsg, nat64Prefix) are reached via reflection/runCatching and reported, not assumed — the prober's purpose is to discover what exists.
  • Hardcoded Linux sockopt ABI numbers live in OsAbi.kt with rationale; do not "fix" them to OsConstants names that don't exist.

Build

From echolot-prober/: ./gradlew :app:assembleDebug (needs local Android SDK; set sdk.dir in echolot-prober/local.properties). The Gradle build is rooted there, not at the repo root. First build downloads AGP/Compose/Shizuku from Google Maven + Maven Central.

Working with test devices (hard-won lessons)

  • Prefer USB for adb. Wireless debugging dies constantly: probe runs churn the wifi the debug link rides on, the Lenovo tablet's ZUI power management kills the listener anyway, and the port rotates on every restart. Deploys over wireless work between runs; never drive a probe run over adb.
  • Collection loop that works: install over adb → the user runs the probes and exports the JSON manually → archive it under echolot-prober/reports/ and record findings in docs/build-status.md.
  • Bump versionCode on every deployed prober change — it shows on screen and as proberBuild in the report; that's how a report is matched to a build.
  • Known devices: OnePlus 15 (CPH2747, A16) — Shizuku UserService works; Lenovo TB330FU (A15, multi-user) — UserService never binds, the newProcess fallback carries it. Full history in build-status.md.
  • Gradle needs JDK 1721 (JAVA_HOME); a system JDK 25 breaks AGP 8.7. On machines with Android Studio, its jbr directory works.

Likely next steps

  1. Run on physical devices; collect JSON reports across Android versions/vendors.
  2. If trace.errqueue_reachable is PARTIAL, add the C-over-JNI errqueue shim (recvmsg + cmsg parse) as a :native module and a real traceroute.udp4 probe.
  3. Fold the confirmed capabilities + Shizuku dump-format samples back into the production core-probe / core-shizuku modules.