Files
ai-app/docs/DECISIONS.md
T
irisandClaude Fable 5.1 1e7b1cddb7 RUST.md, IRIS.md, IRIS_TODO.md, DECISIONS.md: record I5's frame report and holddrag results
FrameReport gave a real, measured on-device number (frames=34,
janky%=61.76, p50=26.5ms p90=48.0ms p99=98.1ms worst=98.1ms) and
long-press-then-drag-to-select is now confirmed on-device (logcat plus a
screenshot of the highlighted selection). Neither closes I5's box to [x]
yet: the frame number is real but not the clean single 24-swipe loop
comparable to Compose's, because gestures against this checkout's
EMU_GPU=software emulator intermittently delivered zero touch input this
session -- a new, separately named finding (candidate cause: the
emulator's own software rasterisation measured at ~78% of a CPU core
continuously), not yet root-caused. DECISIONS.md's DEFERRED item is
updated with these numbers rather than a decision made here.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-05 15:00:29 -04:00

5.8 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/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 (later the same day) with what's now known: iris has its own frame-timing report now (FrameReport) and a real number from it, captured from a genuine on-device touch-drag — frames=34 janky%=61.76 p50=26.5ms p90=48.0ms p99=98.1ms worst=98.1ms — plus a confirmed on-device long-press-then-drag-to-select (logcat and a screenshot of the highlighted selection). It is not yet the clean, comparable number the recommendation wants: gestures against this checkout's EMU_GPU=software emulator intermittently delivered zero touch input during this session, reproducibly, for a reason named but not yet confirmed (the emulator's own software rasterisation measured at ~78% of a CPU core continuously — a plausible source of input backlog, not yet isolated with a sampler running during a failing gesture). The Compose figure quoted for comparison (8.96% janky, 99th percentile 150ms) is the same one already recorded earlier 2026-09-05, not re-taken this pass, and against a different sandbox session's content — so the two numbers share configuration, not identical data. 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 a real if narrowly-scoped frame-timing number), or wait for the touch-delivery investigation above so the comparison can be the single clean 24-swipe loop rather than a number gathered around an unresolved rig flakiness. RUST.md's "Recommendation" item 3 has the full account.