9.4 KiB
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/gfxinfoanswer that cannot see aSurfaceView's GPU-drawn frames.iris_core::FrameReport(iris/core/src/render/frame_report.rs) times each frame's wall clock from the same pointrender()'s redraw starts to just afterqueue.submit+present()— the span Compose's own render report andgfxinfoboth 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 budgetgfxinfouses, 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 viaui-trace, logging under this crate's fixedandroid_loggertag (iris-android-app) so a script can grep"iris frame report"the waytranscript-bench.shgreps"ai-app render report". The report's ownDisplayline says plainly that it measures up to thepresent()call returning, not GPU/compositor completion — wgpu'spresent()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-tracegains a hold-then-drag gesture, additive, inemulator-tools. Neither of its two existing actions can produce "hold stationary forLONG_PRESS, then move without lifting" —taphas no hold andswipe X1 Y1 X2 Y2 MSinterpolates 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 (rawsendevent/MotionEventinjection, extending whatever mechanism the existingswipealready uses), soDragArbiter'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
DragArbiterper 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-appcrate: a winit window holdingtranscript-ui's screen beside a session list, talking to a realai-serverthroughclient-core. It enrols by pasting the sameaiapp://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, theIrisView/MainActivityJava, and the JNI registration; the only thing a second screen needs on top is a differentAndroidAppState, the same axistabs_ui::build/transcript_ui::buildalready vary along on the winit side.tabs-screen/transcript-screenare 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.
-
DECIDED by Iris, 2026-09-05: iris is the app's framework; Masonry was the calibration. Her words: "I think iris definitely makes more sense based on the limitations we've found." The limitations: Masonry has no touch scroll on Android (E2), no per-span rich text and no cross-row selection on the pinned commit (E2), and its keyboard bridge is a TODO (E1); iris carries the same screen under the Compose baseline on the host GPU (p50 15.0 ms against Compose's 20.0 ms, RUST.md's I5 box). What follows: the E-steps are closed as calibration, and the port proceeds on iris — screens, the shell (E3/E5), and
client-coreunderneath. The item below is kept as the record of what she decided from. -
Was 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
SIGSEGVs 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 whichdumpsys gfxinfocannot see at all for iris'sSurfaceView); and both figures are emulator numbers under software rasterisation, which Compose's own in-app report shows already costs 20-34ms/frame inswap+gpualone 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 hostwas 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 (acdthat changed which emulatorui-tracetargeted), 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.Updated 2026-09-05, the
-gpu hostpair taken. Real GPU rendering (force-gles-- the default Vulkan backend has no adapter at all under plain host-GPU boot, confirmed by the exactwgpuerror) reverses the software-mode shape:app build GPU mode frames janky % p50 p90 p99 worst cpu p50 gpu-wait p50 Compose (in-app report) debug host (virgl) 1268 96.4% late 20.0ms 28.4ms 37.7ms -- -- -- iris ( FrameReport)release, force-gleshost (virgl) 62 41.94% 15.0ms 21.8ms 37.1ms 37.1ms 0.2ms 12.9ms Under real GPU rendering iris's median frame is faster than Compose's, not the 2-3x-slower shape the software-mode table shows. A new split inside
FrameReport(redraw-to-submit vs. submit-to-present, commite2a1fad) says why: iris's own CPU work per frame is a median 0.2ms -- almost the entire frame is time spent handing the frame to the driver, not in iris's layout/text/primitive code. This is consistent with the earlier software-mode gap being mostly SwiftShader's CPU rasterisation cost rather than an iris-specific slowness, but is not proof of it: a same-mode softwareforce-glesrun to isolate the backend crashed for an unrelated reason (SwiftShader's GL path reports itself as OpenGL ES 3.0, which has no compute shaders, and iris's device request assumes them unconditionally) — real scope to fix, not done here — and the two apps' frame populations still differ in kind the same way the software-mode caveats describe. A real intermittent touch- scroll dropout was also reproduced this pass (six consecutive swipes produced zero redraws while taps kept working; an identical retry then succeeded) and is not explained. RUST.md's I5 box, "Where iris's frame time goes, 2026-09-05, the-gpu hostpass," has the full account. The iris-vs-Masonry choice itself is still Iris's to make.