docs: the phone-logging decision, how to use it, and two build-apk traps

DECISIONS.md gets the route and both rejected alternatives with what each
would have cost; RUST.md gets a "Phone logging" section with the build
command, where to read it on the phone, the end-to-end verification, and
the two rig traps that cost an hour -- Gradle's merged-native-libs cache
surviving build-apk.sh's `rm -rf jniLibs` (a --abi x86_64 APK packaged
arm64 and aborted with what reads exactly like a Vulkan fault), and the
648 MB debug bench APK that cannot be installed at all. IRIS.md gets the
client-core logging API with a before/after.

Queue item ticked.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Fable 5.1 committed 2026-09-07 16:21:23 -04:00
1 parent 896c93a59a
commit 238057ad5e
3 files changed
+189 -5

No files matched your search

+37
View File
@@ -8,6 +8,43 @@ capability that moved. Small and trivial changes do not go here.
An entry gives the date, what changed, why, and a short before/after where
it helps judge the change without the session that made it. Newest first.
## 2026-09-07: `client-core` carries the app's own log
Not iris itself but the crate beside it, and it is a new public surface an
app author will use: `client_core::log_ring` and `client_core::log_upload`.
Because Iris's phone has no `logcat`, an app now keeps a bounded copy of
its own log and can send it to `ai-server`, where Dev Updater already
shows it.
Before, an app installed a platform logger and that was the end of it:
android_logger::init_once(config); // Android
// nothing at all on the desktop
After, the platform's logger becomes the *inner* logger of a ring that
records everything alongside it -- `logcat` and a terminal see exactly
what they saw before:
client_core::log_ring::install_process_logger(
Box::new(android_logger::AndroidLogger::new(config)),
LevelFilter::Debug,
)?;
let ring = client_core::log_ring::process_ring(); // 2000 lines / 256 KiB
ring.to_text(); // for a report
ring.summary(); // "1801 lines held, 12 dropped, last 20:09:24"
// and, where the app has a server:
let upload = LogUpload::spawn(ring.clone(), transport, "iris-bench", Duration::from_secs(10));
upload.flush_now(); // what `Copy report` calls
upload.status().summary(); // "not tried yet" / "failing -- <why>" / "N lines sent"
`process_ring` is a deliberate process-global, unusually for this project:
`log` already has exactly one backend per process, and a ring passed around
as a parameter would be a second answer to "which lines exist". Dropping
the `LogUpload` handle stops and joins its thread. The wire format is one
new route on `ai-server`, `POST /client-log`; the reasoning and the
rejected alternatives are in docs/DECISIONS.md, 2026-09-07.
## 2026-09-07: `TextData` no longer bundles a font
Iris's call: "remove the font for now; just match what compose does."