Debugging the integration build on real iOS 26.5 devices over the air.
- BitLogger DEBUG default minimumLevel now .debug (was .info) so a
tap-launched sideload surfaces .debug decision logs without the
BITCHAT_LOG_LEVEL env var; env still wins; release unchanged (.info,
emits nothing). Extracted defaultMinimumLevel + a test asserting it.
- Greppable bracket decision tags at .info (visible even at .info) via
SecureLogger, ID-prefixes only, sanitized:
[ROUTE] source-route vs flood origination (+reason) + fragment
targeted-resync; [GW] uplink accept/reject, downlink rebroadcast/drop,
loop skips, drain-timer; [WIFI] offer/accept/decline, AWDL connect,
transfer start/complete+bytes, fallback+reason; [PREKEY] seal choice,
consume, unknown-prekey open fail, bundle ingest, re-gossip;
[SYNC] one concise summary per cycle + per-request served counts (no
per-packet spam); [PING]/[TRACE] RTT + computed path.
- New OSLog categories: mesh, gateway, transport.
- Refactored BLESourceRouteOriginationPolicy.route -> decide returning a
Decision enum (flood(reason)/route(hops)) so the flood reason is
greppable and unit-tested.
- DEBUG-only in-memory ring buffer (LogExportBuffer, ~2000 lines/512KB,
thread-safe, off main thread) + App Info "Export Logs" share sheet
(iOS UIActivityViewController / macOS NSSavePanel), VoiceOver labels.
- DEBUG-only UDP LAN log sink (LogNetworkSink): opt-in, off by default,
fire-and-forget, never blocks/throws; each line prefixed with the
device nickname for demux; configured via App Info host:port fields.
Same sanitized formatted line feeds buffer, sink, and export.
All new code is #if DEBUG; release emits nothing and ships no export/sink UI.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Part A — source-route origination policy:
- Gate route application (BLESourceRouteOriginationPolicy): only packets we
author, directed at a single peer, with TTL headroom, whose recipient is
not directly connected. Relays no longer attach routes to (and re-sign)
packets they merely forward.
- Version-gate paths: MeshTopologyTracker records the highest protocol
version observed per peer; BFS routes require every intermediate hop and
the recipient to be v2-observed, capped at 4 intermediate hops.
- Degrade on failure: BLESourceRouteFailureCache marks a routed send that
sees no inbound traffic from the recipient within 10s as failed and floods
for 60s before retrying routes.
Part B — REQUEST_SYNC fragmentIdFilter (TLV 0x06):
- Requester: BLEFragmentAssemblyBuffer reports stalled broadcast
reassemblies (no new fragment for 5s, retried at most every 10s); the
maintenance pass sends a types=fragment REQUEST_SYNC naming the stalled
8-byte fragment stream IDs to each connected peer.
- Responder: GossipSyncManager restricts the fragment diff to exactly the
named streams, bypassing the since-cursor while the GCS filter still
excludes pieces the requester holds; RSR/TTL-0/rate-limit semantics
unchanged and REQUEST_SYNC stays link-local.
- Bounds: at most 60 IDs per request (60*17-1 = 1019 bytes <= the 1024-byte
decoder cap); oversized 0x06 values are ignored, not fatal.
Docs: SOURCE_ROUTING.md gains the iOS origination policy (§8);
REQUEST_SYNC_MANAGER.md documents 0x05/0x06 as implemented.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>