The app hands its log to Dev Updater on the phone, not through ai-server

Iris's call once the upload route was working: put it in Dev Updater
properly. So the app now exposes its own ring through a ContentProvider
at `<applicationId>.devlog` -- Dev Updater's contract, written down in
that project's README, not something invented here -- and Dev Updater's
phone app reads it on the same device and forwards it to its own build
machine. No tunnel, no token, no second enrolment, and any app that
server delivers can implement the same and get the same Runtime tab.

`DevLogProvider.java` plus `devlog.rs` are the platform glue only: a flat
`String[]` across JNI, a `MatrixCursor` on the Java side, and
`nativeReady` telling Rust the authority the provider actually
registered, so the Diagnostics pane can name somewhere a reader can
query rather than composing a guess. `LogRing::newest_seq()` is the one
addition in `client-core`: an in-memory ring starts again at zero, so it
is what lets a reader notice the process restarted instead of silently
skipping everything since.

Deleted with it, so there is one mechanism: `client_core::log_upload`,
`POST /client-log` on ai-server, the `AI_APP_LOG_*` baking (which left
`build.rs` with nothing to do), and the uploader on both Android
clients. Kept: the ring, `RingLogger`, `install_process_logger`, and the
Diagnostics line -- whose second half is now `devlog provider:
content://<authority>`.

Verified end to end on this checkout's emulator: iris's own
`iris::android::view` startup lines read out of the provider by the
shell, forwarded by Dev Updater's Runtime tab, and served back from
`GET /apps/android-app/components/app/logs?kind=runtime`. A component
whose package has no provider says so in as many words.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Fable 5.1 committed 2026-09-07 20:58:48 -04:00
1 parent e10582a2cd
commit 06b8a1f4b0
15 files changed
+618 -842

No files matched your search

+19 -12
View File
@@ -46,10 +46,9 @@ scrolling never consults the one in `ViewConfiguration`.
## 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.
app author will use: `client_core::log_ring`. Because Iris's phone has no
`logcat`, an app now keeps a bounded copy of its own log and hands it to
Dev Updater on the device.
Before, an app installed a platform logger and that was the end of it:
@@ -68,17 +67,25 @@ what they saw before:
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"
// and, for whatever hands the log out of the process:
let (lines, next) = ring.since(cursor); // inclusive of `cursor`
ring.newest_seq(); // None for a ring nothing was written to
`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.
as a parameter would be a second answer to "which lines exist".
**Amended later the same day.** `client_core::log_upload` and
`ai-server`'s `POST /client-log` are **gone** -- an app no longer sends
its log anywhere. It exposes it on the device instead, and Dev Updater
reads it there: on Android that is a `ContentProvider` at
`<applicationId>.devlog`, which is Dev Updater's own contract (its
`README.md`, "An app's own log") rather than anything iris-specific.
`LogRing::newest_seq()` is the one addition that went with it: a reader
holding a cursor uses it to notice the process **restarted**, since the
ring is in memory and a new process starts again at sequence zero.
The reasoning and the rejected alternatives are in docs/DECISIONS.md,
2026-09-07.
## 2026-09-07: `TextData` no longer bundles a font