Same sandbox session content, same emulator, EMU_GPU=software: Compose (debug, in-app report) 1102 frames/99.0% late/p50 33.8ms/p99 79.5ms vs iris (release -- debug SIGSEGVs on this emulator) FrameReport 299 frames/94.65% janky/p50 79.1ms/p99 117.8ms (repeat: 233/94.42%/p50 109.3ms). Ticks I5 [x]; states plainly what's not comparable (build profile forced asymmetric, three different jank definitions, both are software-rasterised emulator numbers). The two "zero frames" attempts that preceded the clean runs traced to this session's own script bug (a cd into /tmp changed which emulator ui-trace targeted), not a reproduction of the previously-suspected touch-delivery dropout; a sampler ran the whole session and saw load rise during the gesture without correlating to any failure. DECISIONS.md's DEFERRED item gets the same table so Iris can decide iris-vs-Masonry from it -- that choice is left to her. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
107 lines
6.7 KiB
Markdown
107 lines
6.7 KiB
Markdown
# Decisions taken for Iris to review
|
|
|
|
Short list of design choices made by the design agent without asking, so
|
|
they can be judged and reversed later. Detail lives in RUST.md (and IRIS.md
|
|
for iris API changes); this file is only the summary. Newest first. Items
|
|
marked **DEFERRED** are ones the agent chose not to decide alone.
|
|
|
|
## 2026-09-05
|
|
|
|
- **iris gets its own measured frame report, rather than waiting on a
|
|
`dumpsys`/`gfxinfo` answer that cannot see a `SurfaceView`'s GPU-drawn
|
|
frames.** `iris_core::FrameReport` (`iris/core/src/render/frame_report.rs`)
|
|
times each frame's wall clock from the same point `render()`'s redraw
|
|
starts to just after `queue.submit` + `present()` — the span Compose's
|
|
own render report and `gfxinfo` both count — into a fixed 4096-entry
|
|
ring (no allocation per frame; `report()` is the only place that
|
|
allocates, and only on a button tap). The report gives total frames,
|
|
janky % over the same 16.7ms budget `gfxinfo` uses, P50/P90/P99 and the
|
|
worst, plus a reset. Exposed the way the Compose app's copy-button
|
|
report already is: two named controls ("Frame report", "Reset frame
|
|
report") on the transcript screen, tappable by accessibility name via
|
|
`ui-trace`, logging under this crate's fixed `android_logger` tag
|
|
(`iris-android-app`) so a script can grep `"iris frame report"` the way
|
|
`transcript-bench.sh` greps `"ai-app render report"`. The report's own
|
|
`Display` line says plainly that it measures up to the `present()` call
|
|
returning, not GPU/compositor completion — wgpu's `present()` is not
|
|
fenced against either, so presenting that span as "time to reach the
|
|
screen" would be a measured-looking number that is actually inferred,
|
|
which the standing UI rule forbids.
|
|
- **`ui-trace` gains a hold-then-drag gesture, additive, in
|
|
`emulator-tools`.** Neither of its two existing actions can produce
|
|
"hold stationary for `LONG_PRESS`, then move without lifting" — `tap`
|
|
has no hold and `swipe X1 Y1 X2 Y2 MS` interpolates motion across its
|
|
whole duration from t=0. A new action presses, waits, then moves to a
|
|
second point and releases as one continuous touch (raw
|
|
`sendevent`/`MotionEvent` injection, extending whatever mechanism the
|
|
existing `swipe` already uses), so `DragArbiter`'s pan-vs-select rule
|
|
(`iris/src/sense.rs`, already covered by 8 unit tests against a
|
|
synthetic clock) can finally be driven on a real device instead of only
|
|
in a test harness.
|
|
- **Touch drag on a transcript row follows Android's own rule**: a vertical
|
|
drag pans the list immediately; a stationary press held 500 ms starts a
|
|
text selection which further dragging extends; a horizontal drag while
|
|
something is already selected extends that selection without the wait.
|
|
One `DragArbiter` per list decides it (`iris/src/sense.rs`). Chosen over a
|
|
"text layer always wins" or "list always wins" rule because either loses
|
|
one of the two gestures a reader expects.
|
|
- **E4's desktop shape is a new `iris/desktop-app` crate**: a winit window
|
|
holding `transcript-ui`'s screen beside a session list, talking to a real
|
|
`ai-server` through `client-core`. It enrols by pasting the same
|
|
`aiapp://enroll?…` link a phone scans (`client-core::config::EnrolledServer`)
|
|
and keeps it owner-only under `$XDG_CONFIG_HOME/ai-app-desktop/`. The
|
|
pinned CA is a path given on the command line, not baked in. Chosen so
|
|
the phone and desktop share one enrolment format and no second one is
|
|
invented.
|
|
- **I5's Android integration extends `iris-android-app` (I2's shell)
|
|
behind a Cargo feature (`transcript-screen`), rather than a third
|
|
shell crate.** That project already has the Gradle module, the
|
|
`IrisView`/`MainActivity` Java, and the JNI registration; the only
|
|
thing a second screen needs on top is a different `AndroidAppState`,
|
|
the same axis `tabs_ui::build`/`transcript_ui::build` already vary
|
|
along on the winit side. `tabs-screen`/`transcript-screen` are
|
|
mutually exclusive and each pulls in only its own deps, so the plain
|
|
tabs build (I2/I4) is untouched.
|
|
- **Order of remaining work, updated 2026-09-05**: the two in-flight
|
|
pieces and I5's Android integration are all done; next is giving iris
|
|
its own frame-timing report so item 3 below can be decided by a number.
|
|
- **DEFERRED — whether to commit to iris over Masonry for `ai-app`.**
|
|
Updated 2026-09-05 with the clean comparison the recommendation wanted:
|
|
same sandbox session content, same emulator, `EMU_GPU=software`, one
|
|
session. Headline numbers (RUST.md's I5 box, "Clean scroll comparison,
|
|
2026-09-05," has the full table and every caveat):
|
|
|
|
| app | build | frames | janky % | p50 | p90 | p99 | worst |
|
|
|---|---|---|---|---|---|---|---|
|
|
| Compose (in-app report) | debug | 1102 | 99.0% late | 33.8ms | 50.6ms | 79.5ms | -- |
|
|
| Compose (`dumpsys gfxinfo`) | debug | 1499 | 21.15% (95.66% legacy) | 32ms | 48ms | 150ms (p99) | -- |
|
|
| iris (`FrameReport`) | **release** | 299 | 94.65% | 79.1ms | 98.6ms | 117.8ms | 212.6ms |
|
|
| iris (`FrameReport`, repeat) | **release** | 233 | 94.42% | 109.3ms | 130.8ms | 147.1ms | 150.5ms |
|
|
|
|
**Not a clean apples-to-apples reading, stated plainly rather than
|
|
smoothed over**: iris had to be built **release** (debug `SIGSEGV`s on
|
|
this emulator's Vulkan loader, I4's finding) against Compose's mandated
|
|
**debug** build, so this asymmetry likely *understates* iris's gap
|
|
rather than the reverse; the three frame-time sources measure different
|
|
things (Compose's own phase accounting vs. Android's HWUI deadline-miss
|
|
definition vs. iris's redraw-start-to-present window, the last of which
|
|
`dumpsys gfxinfo` cannot see at all for iris's `SurfaceView`); and both
|
|
figures are emulator numbers under software rasterisation, which
|
|
Compose's *own* in-app report shows already costs 20-34ms/frame in
|
|
`swap`+`gpu` alone under this GPU mode, so a same-mode iris number well
|
|
above 16.7ms was expected going in for either app. A second pair under
|
|
`-gpu host` was not taken this pass. The earlier session's suspected
|
|
intermittent touch-delivery dropout was **not reproduced** this pass —
|
|
the zero-frame results this time traced to this pass's own script bug
|
|
(a `cd` that changed which emulator `ui-trace` targeted), not the
|
|
emulator; a CPU-load rise during the gesture was observed by a sampler
|
|
running throughout, but did not correlate with any failure, so the
|
|
original candidate is neither confirmed nor ruled out.
|
|
The choice in front of Iris, updated: decide now on the
|
|
structural-plus-functional case already made (iris works end-to-end
|
|
where Masonry's scroll gesture doesn't exist at all on Android) plus
|
|
this table — reading the two build profiles and three jank definitions
|
|
with the caveats above rather than as a single number — or ask for a
|
|
same-profile, same-GPU-mode rerun first. RUST.md's I5 box has the full
|
|
account.
|