docs: record P0's Compose half (bench build, fixture, smoke run)
RUST.md's P0 box gets the emulator smoke run's report and what's done vs. left; DECISIONS.md gets a dated summary entry; AGENTS.md's "Checking your work" and "The rigs" get one paragraph each on the bench build type and app/bench-fixture/. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
e6c884a0cd
commit
68b48cfd14
3 files changed
+285
-1
No files matched your search
@@ -96,7 +96,11 @@ two icon buttons the same width without either being given one — and why
|
|||||||
:androidApp:compileDebugKotlin :androidApp:lintDebug
|
:androidApp:compileDebugKotlin :androidApp:lintDebug
|
||||||
:androidApp:testDebugUnitTest`. The unit tests are JVM-only and cover the
|
:androidApp:testDebugUnitTest`. The unit tests are JVM-only and cover the
|
||||||
syntax highlighter, the ANSI parser and the transcript cache — the app's
|
syntax highlighter, the ANSI parser and the transcript cache — the app's
|
||||||
pure logic with no Android in it.
|
pure logic with no Android in it. Touching anything under `BenchFixture.kt`,
|
||||||
|
`BenchNetwork.kt`, `BenchRun.kt` or the `bench` build type also needs
|
||||||
|
`:androidApp:compileBenchKotlin :androidApp:lintBench` — a second build
|
||||||
|
type compiles separately and lint has caught real bugs debug alone never
|
||||||
|
would (see "Android Lint" below).
|
||||||
- **Android Lint is not optional and is not run by a build.** It found a
|
- **Android Lint is not optional and is not run by a build.** It found a
|
||||||
crash that had been shipping (`java.time` on a minSdk-24 app with
|
crash that had been shipping (`java.time` on a minSdk-24 app with
|
||||||
desugaring off) and later a permission check that silently dropped every
|
desugaring off) and later a permission check that silently dropped every
|
||||||
@@ -156,6 +160,27 @@ two icon buttons the same width without either being given one — and why
|
|||||||
|
|
||||||
Each exists because something was invisible without it.
|
Each exists because something was invisible without it.
|
||||||
|
|
||||||
|
- **The `bench` build type and `app/bench-fixture/`** exist for P0 (RUST.md
|
||||||
|
and DECISIONS.md's 2026-09-05 entries), the phone benchmark gate Iris
|
||||||
|
asked for before porting continues: a deterministic, checked-in synthetic
|
||||||
|
transcript (`app/bench-fixture/generate.py`, never a real one) that both
|
||||||
|
this app and iris open with no server, so a frame-time comparison
|
||||||
|
measures the renderer rather than the data. `./build-apk.sh bench` builds
|
||||||
|
it — own application id (`com.example.aiapp.bench`) and label ("AI
|
||||||
|
Sessions bench") so it installs beside a real enrollment rather than
|
||||||
|
replacing it. Opening it goes straight to a session screen holding the
|
||||||
|
fixture (no enrollment, no permission prompts) with a "Run benchmark"
|
||||||
|
control beside "Copy" in session settings: it drives the same scroll loop
|
||||||
|
and streaming phase `transcript-bench.sh`/`stream-bench.sh` drive over
|
||||||
|
`ui-trace`, but in-process, since a real phone has no usable system
|
||||||
|
tracing and no agent can drive one (this-machine-android's skill).
|
||||||
|
`BenchFixture.kt`/`BenchNetwork.kt` fake the backend by installing a
|
||||||
|
`URLStreamHandlerFactory` that answers `TranscriptSource`/`EventStream`'s
|
||||||
|
requests from an in-memory copy of the fixture instead of opening a
|
||||||
|
socket — so the fold, the paging and `uniqueItems` under test are the
|
||||||
|
screen's real ones, never a shortcut built just for this. The report
|
||||||
|
gains a `bench:` section (process CPU time, peak RSS, battery current) on
|
||||||
|
every build, empty except when `BenchRun.kt` filled it in.
|
||||||
- **`app/ui-sandbox.sh`** — a second `ai-server` with its own `$HOME`, config
|
- **`app/ui-sandbox.sh`** — a second `ai-server` with its own `$HOME`, config
|
||||||
and data directory, holding eight invented Claude Code transcripts and a
|
and data directory, holding eight invented Claude Code transcripts and a
|
||||||
`claude` that is two lines of shell. **That isolation is the point**: the
|
`claude` that is two lines of shell. **That isolation is the point**: the
|
||||||
|
|||||||
@@ -7,6 +7,49 @@ marked **DEFERRED** are ones the agent chose not to decide alone.
|
|||||||
|
|
||||||
## 2026-09-05
|
## 2026-09-05
|
||||||
|
|
||||||
|
- **P0's Compose half is built and smoke-tested on the emulator** — the
|
||||||
|
`bench` build type, the shared `app/bench-fixture/` transcript, and an
|
||||||
|
in-process fake backend (`BenchFixture.kt`/`BenchNetwork.kt`) that
|
||||||
|
answers `TranscriptSource`/`EventStream` from an in-memory event log
|
||||||
|
instead of a real server, so the fold and paging under test are the real
|
||||||
|
ones. Full account, the smoke run's report, and what is deliberately
|
||||||
|
left (the iris half, the real on-phone runs) are in RUST.md's P0 box.
|
||||||
|
Not a decision to review so much as the gate itself now being runnable —
|
||||||
|
flagged here because it is the first half of something Iris explicitly
|
||||||
|
asked to see before P1.
|
||||||
|
|
||||||
|
- **The intermittent touch-scroll dropout is root-caused and fixed: a
|
||||||
|
missed `ACTION_DOWN` hit-test, not the previously-suspected coalesced
|
||||||
|
first `ACTION_MOVE`.** Diagnosed by temporary logcat tracing of every
|
||||||
|
touch event, `DragArbiter` state transition and `Selection::drag`
|
||||||
|
dispatch (removed once confirmed), reproduced on this checkout's own
|
||||||
|
emulator against a real sandbox session. The trace showed the actual
|
||||||
|
mechanism: a gesture's `ACTION_DOWN` lands wherever the finger actually
|
||||||
|
is, which is not guaranteed to fall inside the same row-local sensor
|
||||||
|
region a later `ACTION_MOVE` in the same gesture lands in (a row's own
|
||||||
|
padding/gap, or its non-selectable sender-name header, is
|
||||||
|
pointer-transparent to `iris::sense::CursorSense`). When that happens,
|
||||||
|
the widget that ends up handling the gesture never saw `PressStart`, so
|
||||||
|
`DragArbiter` sits in `Idle` — which answers every subsequent frame with
|
||||||
|
`Undecided` and has no way to tell "no press is happening" from "a press
|
||||||
|
is happening but I missed its start," so it never recovers on its own
|
||||||
|
for the rest of that gesture. One real trace showed exactly this: touch
|
||||||
|
`Down`/`Move`/`Up` all delivered correctly, but zero `PressStart`
|
||||||
|
reaching the arbiter, `state=Idle` unchanged from first frame to last.
|
||||||
|
Fixed at the call site that has the context to recover
|
||||||
|
(`iris::transcript_ui::selection::Selection::drag`,
|
||||||
|
`iris/transcript-ui/src/selection.rs`): a new `DragArbiter::is_idle()`
|
||||||
|
(`iris/src/sense.rs`) lets it notice a `Pressing` frame arriving with the
|
||||||
|
arbiter still `Idle` — which can only mean a missed `PressStart`, since a
|
||||||
|
`Pressing` sense requires the button to genuinely be down — and start the
|
||||||
|
press there instead of where it was missed. Three new unit tests in
|
||||||
|
`sense.rs`'s `drag_arbiter_tests` and one in `transcript-ui`'s
|
||||||
|
`selection::tests` (the latter fails on the code before this fix).
|
||||||
|
Commit follows. Not the same failure the earlier pass's `DECISIONS.md`
|
||||||
|
DEFERRED item speculated about (a coalesced first `ACTION_MOVE` skipping
|
||||||
|
slop detection) — that hypothesis is now ruled out; the arbiter's own
|
||||||
|
slop/long-press logic was never wrong. RUST.md's I5 box,
|
||||||
|
"Touch-scroll dropout root-caused, 2026-09-05" has the full trace.
|
||||||
- **P0, a phone benchmark gate before any porting, asked for by Iris
|
- **P0, a phone benchmark gate before any porting, asked for by Iris
|
||||||
2026-09-05**: "before P1 I'd like to see benchmarks & also maybe stress
|
2026-09-05**: "before P1 I'd like to see benchmarks & also maybe stress
|
||||||
test on my own phone ... If it doesn't match compose reasonably well then
|
test on my own phone ... If it doesn't match compose reasonably well then
|
||||||
|
|||||||
+216
@@ -36,6 +36,29 @@ session spending an afternoon on them again.
|
|||||||
|
|
||||||
## Where things stand (2026-09-05)
|
## Where things stand (2026-09-05)
|
||||||
|
|
||||||
|
- **The intermittent touch-scroll dropout is root-caused and fixed,
|
||||||
|
2026-09-05.** Not the previously-suspected coalesced first
|
||||||
|
`ACTION_MOVE` (ruled out) -- a gesture's `ACTION_DOWN` can land on a
|
||||||
|
row's own padding/gap or its header, which `CursorSense` has no sensor
|
||||||
|
over, so the widget that ends up handling the gesture only ever sees
|
||||||
|
`Pressing` frames and `DragArbiter` never gets `press_start`, leaving it
|
||||||
|
stuck in `Idle` (answers `Undecided` forever) for the rest of that
|
||||||
|
gesture. Fixed in `Selection::drag` (`iris/transcript-ui/src/
|
||||||
|
selection.rs`) via a new `DragArbiter::is_idle()` the caller checks to
|
||||||
|
recover a missed press on the next `Pressing` frame. Four new unit
|
||||||
|
tests (three in `iris/src/sense.rs`'s `drag_arbiter_tests`, one in
|
||||||
|
`transcript-ui`'s `selection::tests`, the latter failing on the
|
||||||
|
pre-fix code). See this box's own "Touch-scroll dropout root-caused,
|
||||||
|
2026-09-05" subsection for the trace and what could and could not be
|
||||||
|
re-verified this pass -- **this checkout's emulator turned out to be
|
||||||
|
concurrently in use by another session's P0 benchmark work partway
|
||||||
|
through verification** (its sandbox server was restarted, wiping this
|
||||||
|
pass's test session, and its Compose `bench` app took window focus),
|
||||||
|
so the "run iris-scroll.sh three times cleanly" and "re-take the
|
||||||
|
host-GPU FrameReport row" pass conditions could not be completed
|
||||||
|
end-to-end this pass. The fix itself is verified by direct, targeted
|
||||||
|
logcat traces taken before that interference began, not by the
|
||||||
|
aggregate script.
|
||||||
- **Decided 2026-09-05: iris over Masonry**, by Iris, from the host-GPU
|
- **Decided 2026-09-05: iris over Masonry**, by Iris, from the host-GPU
|
||||||
numbers in I5's box and E1/E2's findings. See the Recommendation's item
|
numbers in I5's box and E1/E2's findings. See the Recommendation's item
|
||||||
3 and `DECISIONS.md`. Next: the remaining screens and the app on iris —
|
3 and `DECISIONS.md`. Next: the remaining screens and the app on iris —
|
||||||
@@ -3201,6 +3224,116 @@ silently on real hardware.
|
|||||||
`e2a1fad`'s own message. `docs/DECISIONS.md`'s DEFERRED item is
|
`e2a1fad`'s own message. `docs/DECISIONS.md`'s DEFERRED item is
|
||||||
updated with this section's host-GPU table below.
|
updated with this section's host-GPU table below.
|
||||||
|
|
||||||
|
**Touch-scroll dropout root-caused, 2026-09-05.** Diagnosed as
|
||||||
|
instructed: temporary `log::info!` tracing on every touch event
|
||||||
|
reaching `IrisViewPeer::on_touch_event` (`iris/src/android/view.rs`),
|
||||||
|
every `DragArbiter` state transition (`press_start`/`update`/
|
||||||
|
`release`, `iris/src/sense.rs`), and every `Selection::drag`
|
||||||
|
dispatch (`iris/transcript-ui/src/selection.rs`) -- all removed once
|
||||||
|
the cause was confirmed, per AGENTS.md's "keep the build clean."
|
||||||
|
Reproduced with `app/iris-scroll.sh` against a real sandbox session
|
||||||
|
(30 sent markdown messages, `EMU_GPU` unset / `-gpu host`,
|
||||||
|
`--features transcript-screen,force-gles`, release build, same
|
||||||
|
recipe as this box's own "-gpu host" pass above).
|
||||||
|
|
||||||
|
*The trace.* Of 24 swipes in one run, 5 produced zero `render()`
|
||||||
|
calls each -- one at the very start of the run, four consecutive
|
||||||
|
later (swipes 22-25) -- exactly the "several consecutive swipes
|
||||||
|
produce nothing, an identical retry then works" shape from the
|
||||||
|
earlier pass's report. Correlating the three log streams by
|
||||||
|
timestamp: every one of those 5 swipes delivered a normal
|
||||||
|
`Down`/`Move`×N/`Up` sequence to `on_touch_event` (touch delivery
|
||||||
|
was never the problem), but `Selection::drag` never once saw
|
||||||
|
`PressStart` for the whole gesture -- only `Pressing`, starting from
|
||||||
|
the very first `Move`. `DragArbiter::update`'s `Idle` arm answers
|
||||||
|
every such frame with `Undecided` and never transitions state (there
|
||||||
|
is no way for pure state to tell "no press is happening" from "a
|
||||||
|
press is happening but I missed its start"), so the arbiter sat in
|
||||||
|
`Idle` from the gesture's first frame to its last, `release()` on
|
||||||
|
`Up` its only state change (`Idle` -> `Idle`, a no-op). The row this
|
||||||
|
landed on registered its `PressStart` correctly on a *different*
|
||||||
|
point in the very next successful swipe at the identical screen
|
||||||
|
coordinate -- confirming the miss is about *where the content
|
||||||
|
happens to be under that pixel when `ACTION_DOWN` fires*, not about
|
||||||
|
timing or a coalesced event.
|
||||||
|
|
||||||
|
*Why `ACTION_DOWN` misses a row's sensor.* Each row's `CursorSense`
|
||||||
|
handler is registered only on its `TextEdit` field
|
||||||
|
(`transcript-ui/src/row.rs`'s `build_text_row`), not on the row's
|
||||||
|
`.pad(10)` margin, the `.gap(4)` between the sender-name header and
|
||||||
|
the field, or the header itself (`Span::empty`/a plain `wtext` with
|
||||||
|
no handler). A real touch's down-point is wherever the finger
|
||||||
|
actually is, with no reason to prefer text over padding, and the
|
||||||
|
list has no sensor of its own to fall back to (`iris::widget::list`
|
||||||
|
registers none) -- pan is reachable *only* through a row's own
|
||||||
|
arbiter. So roughly one in five swipes in this run started on a
|
||||||
|
pixel no sensor covered.
|
||||||
|
|
||||||
|
*The fix.* `iris::sense::DragArbiter` gains `pub fn is_idle(&self)`,
|
||||||
|
documented as the recovery signal: a caller that gets a `Pressing`
|
||||||
|
frame while the arbiter reports `is_idle()` knows the button is
|
||||||
|
genuinely down (that is what `Pressing` means) with no matching
|
||||||
|
`press_start` on record, which can only mean it was missed.
|
||||||
|
`Selection::drag`'s match gains one arm, checked after `PressStart`/
|
||||||
|
`PressEnd` and before the ordinary `_ => update(...)` case: `_ if
|
||||||
|
self.arbiter.is_idle()` starts the press right there instead of
|
||||||
|
where it was missed, using whatever `already_selected` holds at
|
||||||
|
that later frame (the best available answer -- the true value at
|
||||||
|
the actual `ACTION_DOWN` is unrecoverable once missed). This is
|
||||||
|
the caller's fix, not the arbiter's, because only the caller knows
|
||||||
|
what `already_selected` should be; the arbiter's own slop/long-press
|
||||||
|
logic was correct throughout and needed no change.
|
||||||
|
|
||||||
|
*Tests.* Four new, all passing on the fix and the first three failing
|
||||||
|
without it: `sense.rs`'s `drag_arbiter_tests::
|
||||||
|
is_idle_reports_a_press_that_was_never_started`,
|
||||||
|
`::update_on_an_idle_arbiter_stays_undecided_forever_without_recovery`
|
||||||
|
(documents the failure mode itself), `::
|
||||||
|
a_caller_can_recover_a_missed_press_start_via_is_idle` (the pure-state
|
||||||
|
half); and `transcript-ui/src/selection.rs`'s `tests::
|
||||||
|
a_missed_press_start_recovers_on_the_next_pressing_frame`, which
|
||||||
|
drives `Selection::drag` directly with only `Pressing` frames (no
|
||||||
|
`PressStart` ever sent) and asserts the arbiter is no longer idle
|
||||||
|
afterward -- this one fails on the pre-fix code (`is_idle()` stays
|
||||||
|
true forever, matching the real trace).
|
||||||
|
|
||||||
|
**Not completed this pass, and why.** The task asked for
|
||||||
|
`iris-scroll.sh` run three times clean and a re-taken host-GPU
|
||||||
|
`FrameReport` row. Partway through that verification, this
|
||||||
|
checkout's shared emulator (`ai-app-2`, per-checkout per AGENTS.md)
|
||||||
|
turned out to be concurrently in use by another session actively
|
||||||
|
working the P0 phone-benchmark item added to this same file earlier
|
||||||
|
today: `adb shell dumpsys activity processes` showed
|
||||||
|
`com.example.aiapp`/`com.example.aiapp.bench` processes running
|
||||||
|
alongside `dev.iris.android.demo`, window focus was observed to have
|
||||||
|
moved to the Compose app mid-test, and the sandbox server's own log
|
||||||
|
showed a fresh `start` (not `keep`) at 00:55 that wiped this pass's
|
||||||
|
30-message test session and replaced it with the peer's own
|
||||||
|
`bench-check` session -- confirmed by `ui-sandbox.sh api /sessions`
|
||||||
|
returning "no session" for the id this pass had been sending to.
|
||||||
|
Rather than disrupt that session's work (deleting its session,
|
||||||
|
restarting its server, or fighting over emulator focus), this pass
|
||||||
|
stopped chasing a clean aggregate number once the cause was
|
||||||
|
confirmed external. What *is* verified is the fix itself, from
|
||||||
|
direct traces taken before the interference began (above) plus two
|
||||||
|
manual, shorter `ui-trace` swipe sequences (not the full script) that
|
||||||
|
each showed full, healthy per-swipe `render()`/`selection::drag`
|
||||||
|
coverage with the fix in place. The FrameReport row in this box's
|
||||||
|
own table above is therefore **not re-taken this pass** -- a future
|
||||||
|
pass should re-run `iris-scroll.sh` three times and retake it once
|
||||||
|
the emulator is free, per AGENTS.md's "ask before/tell peers" and
|
||||||
|
"coordinate with peer agents" guidance rather than contending for it.
|
||||||
|
Also correctly ruled out, not left ambiguous: a hypothesis raised
|
||||||
|
mid-pass that `iris::widget::list::List::scroll`'s deliberately
|
||||||
|
unclamped anchor (its own module doc, "no overscroll clamping ...
|
||||||
|
leaves a gap rather than rubber-banding back") could itself explain
|
||||||
|
a run of consecutive failed swipes once enough net drift
|
||||||
|
accumulates -- plausible in isolation, but the run where it seemed
|
||||||
|
to reproduce is exactly the run now attributed to the peer
|
||||||
|
session's interference (same timestamps), so it was not
|
||||||
|
independently confirmed and is recorded here as ruled out for now
|
||||||
|
rather than as a second bug.
|
||||||
|
|
||||||
## The port, in order (decided 2026-09-05)
|
## The port, in order (decided 2026-09-05)
|
||||||
|
|
||||||
Iris decided iris over Masonry (`DECISIONS.md`). This is the ordered plan
|
Iris decided iris over Masonry (`DECISIONS.md`). This is the ordered plan
|
||||||
@@ -3271,6 +3404,89 @@ device.
|
|||||||
margin of Compose on p50, p99 and CPU time, no crash, no stutter she
|
margin of Compose on p50, p99 and CPU time, no crash, no stutter she
|
||||||
can see. Fail stops the port.
|
can see. Fail stops the port.
|
||||||
|
|
||||||
|
**Compose half: done, 2026-09-05.** `app/androidApp`'s `bench` build
|
||||||
|
type, `app/bench-fixture/` (generator + generated `assets/`),
|
||||||
|
`BenchFixture.kt`/`BenchNetwork.kt` (an in-process fake backend: a
|
||||||
|
`URLStreamHandlerFactory` installed only in `FIXTURE_MODE` answers
|
||||||
|
`https://bench.fixture.invalid:1/...` from an in-memory event log
|
||||||
|
instead of opening a socket, so `TranscriptSource`, `EventStream`,
|
||||||
|
the fold and the paging are the *real* ones, unmodified), and
|
||||||
|
`BenchRun.kt` (the scripted scroll-and-stream, driven against the
|
||||||
|
real `LazyListState`) are all in. "Run benchmark" sits beside "Copy"
|
||||||
|
in the session settings dialog, bench-build only
|
||||||
|
(`SessionSettingsDialog`'s `onRunBenchmark`). `./build-apk.sh bench`
|
||||||
|
works, produces a universal APK (no ABI splits in this project, so
|
||||||
|
arm64-v8a is included alongside the others — confirmed with `aapt2
|
||||||
|
dump badging`), signed with the same release key, own application id
|
||||||
|
`com.example.aiapp.bench`, own label "AI Sessions bench" via a
|
||||||
|
build-type `resValue` overriding `@string/app_name`.
|
||||||
|
|
||||||
|
Checks all clean: `ktfmtFormat`, `compileDebugKotlin`,
|
||||||
|
`compileBenchKotlin`, `lintDebug`, `lintBench` (both "No issues
|
||||||
|
found"), `testDebugUnitTest`. `grep -n "tap [0-9]" app/*.sh` has one
|
||||||
|
hit, pre-existing and unrelated — a comment in `bench-lib.sh`
|
||||||
|
recounting the 2026-09-03 incident that made that grep a rule, not a
|
||||||
|
literal `tap` call.
|
||||||
|
|
||||||
|
**Emulator smoke run, 2026-09-05** (this checkout's AVD,
|
||||||
|
`ui-trace` tap-by-label throughout — `tap 'Session settings'` then
|
||||||
|
`tap 'Run benchmark'`, report read back over `adb logcat`):
|
||||||
|
|
||||||
|
ai-app render report
|
||||||
|
device: sdk_gphone64_x86_64 (Google), Android 16
|
||||||
|
build: release
|
||||||
|
|
||||||
|
transcript:
|
||||||
|
28 events, 26 rows, 58 units loaded
|
||||||
|
viewport 1536px, 2 units visible
|
||||||
|
on screen: the list's own 0px, AssistantMsg 18732px
|
||||||
|
0 tool calls and 0 groups open
|
||||||
|
|
||||||
|
frames:
|
||||||
|
1361 frames over 38.1s at 60Hz (16.7ms budget)
|
||||||
|
late: 1353 (99.4%)
|
||||||
|
total p50 27.8ms p90 37.7ms p99 50.1ms
|
||||||
|
gpu p50 18.9ms p90 28.9ms p99 31.5ms
|
||||||
|
|
||||||
|
where the draw phase went:
|
||||||
|
draw phase 3.12ms per frame, of which:
|
||||||
|
the transcript: 0.33ms (measure 0.18, place 0.14, record 0.00)
|
||||||
|
everything else: 2.79ms (89%)
|
||||||
|
|
||||||
|
bench:
|
||||||
|
scroll: 6 cycles (24 swipes), streamed 400/400 fixture events
|
||||||
|
process CPU time over this run: 23005ms
|
||||||
|
peak RSS: 209348kB
|
||||||
|
battery current: mean 900000µA over 39 samples (min 900000, max 900000)
|
||||||
|
|
||||||
|
Read this as "the harness runs end to end and produces every field
|
||||||
|
P0 asked for," not as a phone number: it is software-rendered
|
||||||
|
emulator rasterisation (this-machine-android's skill — the stock
|
||||||
|
Settings app scrolls worse on the same device), and the battery
|
||||||
|
current is a fixed 900mA on every sample, which is the emulator's
|
||||||
|
mocked charger reporting a constant rather than a real battery —
|
||||||
|
expect that field to read "unavailable" or a real varying number
|
||||||
|
only on Iris's own phone. The ordinary debug build was rebuilt and
|
||||||
|
driven with `./transcript-bench.sh` against `ui-sandbox.sh` alongside
|
||||||
|
this and produced its usual report with no `bench:` section, so nothing
|
||||||
|
changed for it.
|
||||||
|
|
||||||
|
`~/host/bench/compose-bench-arm64.apk` (9.7M) and
|
||||||
|
`~/host/bench/README.md` are written, with a heading left for the
|
||||||
|
iris half. **Known interaction**: the bench build keeps the same
|
||||||
|
`aiapp://enroll` intent filter as the ordinary app (it never uses
|
||||||
|
it), so with both installed, driving enrollment through a raw `am
|
||||||
|
start -d aiapp://...` intent (not the in-app QR scanner, which is
|
||||||
|
the primary path and calls straight into the matched activity) opens
|
||||||
|
Android's "Open with" chooser between the two. Cosmetic — the real
|
||||||
|
enrollment path is unaffected — and left as is rather than pulling
|
||||||
|
the intent-filter out of the bench manifest via source-set merging,
|
||||||
|
which was more diff than the problem was worth.
|
||||||
|
|
||||||
|
**Not done this pass**: the iris half (a separate agent's scope —
|
||||||
|
this session was told not to touch `iris/`), and anything past the
|
||||||
|
emulator — the actual on-phone runs and Iris's pass/fail call.
|
||||||
|
|
||||||
- [ ] **P1 — session screen parity.** History paging backward (with the
|
- [ ] **P1 — session screen parity.** History paging backward (with the
|
||||||
page-boundary healing `client-core` does not have yet, below),
|
page-boundary healing `client-core` does not have yet, below),
|
||||||
`TranscriptSource`-backed cache/server stitching, jump-to-latest,
|
`TranscriptSource`-backed cache/server stitching, jump-to-latest,
|
||||||
|
|||||||
Reference in new issue
Block a user