Keep the borrowed audio provider on UTUN_INSTANCE across chat service restarts.
Attach and detach Android voice from the core worker and reject DSP startup
after detach. Preserve TX owner epochs, pending slots and foreign-instance RX
isolation. Remove the unused cross-thread online API and keep its check local
to call.c.
Add eight lifecycle regressions with real cores and the Android host bridge.
Audit public call, DSP, clock, headless and desktop audio contracts and record
the findings and validation scope.
Validation: voice/desktop 38/38, four native call suites, native and both Android
ABI builds, full check 204/204 plus proxy/burst/load. JVM results remain Gradle
UP-TO-DATE (155 app and 15 router). No hardware runtime validation.
Refresh both AGENTS guides and clarify module purpose, usage, ownership, threading, return values and wire formats in headers. Remove the unused timeout_heap freed_count field and unimplemented getter.
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
- instance_lite.h/c: full uTun stack from INI config text
(keygen, uasync, UTUN_INSTANCE, SQLite, chat_core/sync, BGP, etcp_router)
- jni_bridge: nativeStart/Stop, nativeJoinChannel → chat_sync_connect_from_invite,
nativeSubscribeLogs, C logs → logcat + Kotlin LogManager
- Kotlin: direct read-only SQLite queries (channels, messages),
ViewModel with live event callbacks, reactive LogScreen (tail -f),
CameraX QR scanner with proper lifecycle, JoinChannelDialog
- HeadlessService: generates INI config from Kotlin settings → C instance