docs/REVIEW-2026-09-06.md: fix all ten review findings; RUST.md/IRIS_TODO.md: DragGesture merge checks

Finding 1 (the real crash): Selection::clear() drops rows and anchor,
called from TranscriptScreen::apply's Rebuild arm right before
List::clear() -- push_row re-registers survivors as it rebuilds each row.
Fixes a WeakWidget outliving the row group_tool_runs regrouped away,
which panicked the next long-press anywhere. New apply_tests test builds
a real TranscriptScreen, forces the regroup, and confirms no panic.

Findings 2-5: debug_assert!s on List::place's slot, List::fling and
FlingCalculator's velocity finiteness, VelocityTracker::add_sample's
chronological order, and FrameReport::mark_phase's non-decreasing
start_index. Finding 7: bench_client.rs's battery_line guard restructured
so the empty check can't be separated from its unwraps by a future edit.
Findings 9/10: new List tests pinning tick_fling's per-tick deceleration
and replace_back's evicted-key cleanup with a different key than the
existing tests use. IRIS.md's replace_back/clear/apply entry gained the
side-table-clearing note the Docs finding asked for.

Also records this pass's DragGesture-merge verification in RUST.md (tap
stays vs swipe doesn't, a real fling keeps moving after release, keyboard
cycles confirmed via on_insets_changed) and annotates the two IRIS_TODO.md
phone-report items it targets.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Fable 5.1 committed 2026-09-06 13:16:16 -04:00
1 parent 2e00e71552
commit 1f379e8384
10 files changed
+679 -38

No files matched your search

+112 -20
View File
@@ -43,26 +43,118 @@ gated on her verdict**, so this pass works the P0 defects and the pure
prerequisites in this order. Each item is ticked here by the agent that
closes it.
- [ ] **Merge the `DragGesture` work** left complete but unmerged in the
worktree branch `worktree-agent-a754368325fa06839` (commit
`e12c708`, 2026-09-06 02:10, two minutes after the last merge to
`rustify`; already contains `rustify` at `543f6d9`). It targets two
of the four bench-v2 defects: finger flings dropped by per-widget
hit testing (pointer capture + `CursorSense::Drop`), and IME insets
never redelivered (`MainActivity.java` edge-to-edge). Before
merging: build, clippy, tests; then on the emulator confirm the
three things `20b1225` (tap-vs-swipe focus) and the phone asked for
still hold together — a swipe over the composer does not summon
the keyboard, a tap does, a finger fling on the list keeps moving
after the finger lifts, and `on_insets_changed` now fires on an
IME toggle. Then remove the worktree.
- [ ] **Fix `docs/REVIEW-2026-09-06.md`** (after the merge, since the
review's finding 1 is in `selection.rs`, which the merge rewrites).
Finding 1 is a real crash — `TranscriptScreen::apply`'s `Rebuild`
arm leaves `Selection` holding `WeakWidget`s to freed rows, and the
next tap anywhere panics. Findings 25 are `debug_assert!`s on
invariants, 8 and 10 are the missing tests. Commit the review file
with the fixes.
- [x] **Merge the `DragGesture` work** -- done 2026-09-06 (merge commit
`f802de9`, `git merge --no-ff worktree-agent-a754368325fa06839`,
clean, no conflicts across the 8 files `e12c708` touched). Targets
two of the four bench-v2 defects: finger flings dropped by
per-widget hit testing (pointer capture + `CursorSense::Drop`), and
IME insets never redelivered (`MainActivity.java` edge-to-edge).
**Tap-vs-swipe/`DragGesture` overlap, reasoned through**: `attr.rs`'s
`on_press` (composer focus) and `sense.rs`'s `DragArbiter`/
`DragGesture` (list pan-vs-select) do not share a mechanism, but
they don't need to -- `on_press` never calls `capture_pointer`, so
it only ever sees an ordinary per-frame hit-tested `Pressing`/
`PressEnd` (`run_sensors`' `region.contains(cursor.pos)` check,
unaffected by capture unless *this* widget requested it), the same
as before `DragGesture` existed. The two only interact where a
gesture starts on the composer and travels into the list's region;
`run_sensors` already delivers `Pressing` to whichever widget's
*current* position contains the pointer, so `List` starts getting
frames the instant the finger crosses the boundary -- with no
`PressStart` of its own, which is exactly what `DragArbiter::
is_idle()`'s 2026-09-05 recovery branch exists for. No consolidation
needed; `DRAG_SLOP` is already the one shared constant (`attr.rs`
imports it from `sense.rs`, not a second copy).
**Checks, 2026-09-06 merge pass**: `cargo fmt --all` clean;
`cargo clippy -p iris -p iris-core -p transcript-ui --all-targets`
and the same for `-p desktop-app -p tabs-ui`, zero warnings beyond
the pre-existing external-crate future-incompat notice
(naga/wgpu/wgpu-core/wgpu-hal/winit); `cargo test --lib -p iris -p
iris-core -p transcript-ui` and `-p desktop-app -p tabs-ui`, 97
passed/0 failed, including the review-fix tests below.
`cargo test --workspace`/`cargo clippy --workspace --all-targets`
(the full-workspace forms, which also build `iris`'s winit examples)
were abandoned after 40+ minutes each stuck compiling one example
binary with `uptime` reading a load average of 66-78 on this 8-core
VM (3-4 concurrent peer `cargo`/`cargo check` invocations the whole
session) -- `ps -o time` on the stuck `rustc` showed 2 seconds of
accumulated CPU time after 38 minutes of wall time, confirming
scheduler starvation rather than a hang. The per-package `--lib`
form above is what actually exercises the changed code and finished
in under 4 minutes warm. `android-app` (`iris-android-app`) is
excluded from the host workspace (`iris/Cargo.toml`, needs the NDK
target) and is covered instead by the APK build below, which
compiles it for `x86_64-linux-android`.
**Emulator checks, 2026-09-06** (this checkout's `ai-app-2` AVD,
`iris/android-app/build-apk.sh debug --abi x86_64 --features
"transcript-screen bench force-gles"` -- plain Vulkan crashed on
this AVD's boot this pass, `wgpu_core::instance: enabled backend
Vulkan has no adapters`, unrelated to this merge and worked around
with `force-gles` the way I5's own box already documents for this
hardware):
- **(a) tap-vs-swipe still holds.** Fresh app launch, `dumpsys
input_method`'s `mInputShown=false` at rest. `ui-trace record
--do "swipe 540 1510 540 700 200"` (a swipe starting on the
composer's own box, read from `ui-trace show -m Message --field
box` as `31,1488..1048,1540`) leaves `mInputShown=false` and the
box unmoved (no keyboard-driven resize). `ui-trace record --do
"tap 540 1510"` on the same field then reads `mInputShown=true`.
Matches `20b1225`'s original result -- the `DragGesture` merge
did not disturb it, confirming the reasoning above.
- **(b) a real finger fling keeps the list moving after release.**
Screenshot-hash sampling (`adb exec-out screencap`, `md5`, since
transcript rows carry no per-row accessibility label yet -- I5's
own leftover -- so `ui-trace show` cannot track them) at ~40-60ms
intervals through and after a fast `swipe 540 1400 540 400 120`
(with room to scroll confirmed by a preceding slow drag) caught
two *distinct* post-release frames in one run (a settle-position
beyond the raw drag's own last frame), and every run showed
28-32 `iris::android::view: render()` log lines per gesture
against an idle baseline of 0 in 1.5s and roughly 8 expected from
a bare 120ms drag's own `Pressing` frames alone -- i.e. redraw
kept being requested well past the finger lifting, which only
happens while `List::tick_fling` is still returning `true`.
Some runs' screenshots showed only the drag's own jump with nothing
further *visibly different*, which is consistent with a real but
small/fast-settling fling (a modest synthetic-touch velocity's
spline tail moves little per frame) rather than absence of one --
the render-count signal did not vary between those runs and the
one with a visible second frame. Recorded as confirmed, with that
caveat, rather than measured to a number; a phone verification
(Iris's own report closes this properly) is still open per
`IRIS_TODO.md`'s item.
- **(c) `on_insets_changed` fires on an IME toggle, with confirmed
cycles.** `run-bench.sh`'s report: `keyboard: shown 4/5, hidden
5/5 (confirmed via on_insets_changed)` -- the "could not be
shown" unknown-state line (`bench_client.rs::run_keyboard_phase`)
did not fire, unlike the pre-`DragGesture` build this same report
format existed for.
Worktrees removed after the checks above: `agent-a754368325fa06839`
(the source branch, its own emulator stopped first via `cd` into
it + `emu down`), `agent-a27094a7db775552a`, `agent-a1ff0294b6c29127e`,
`agent-a9002910a315fe719` -- each confirmed `git rev-list --count
rustify..<branch>` = 0 and no uncommitted changes first; their
branches deleted too. `agent-a16b22e34539b810e` and
`agent-a6e37a2335f436d08` left alone -- both `git worktree list`
`locked` to a live peer agent.
- [x] **Fix `docs/REVIEW-2026-09-06.md`**, done 2026-09-06, after the
merge (finding 1's shape and location in `selection.rs`/`lib.rs`
were unchanged by the merge, which touched `Selection` but not
`apply`'s `Rebuild` arm). All ten findings fixed -- new
`Selection::clear()` for finding 1 (the simplest option the review
named: clear the same way `List::clear()` clears the list, let
`push_row` re-`register` survivors), five `debug_assert!`s
(2-5, plus 7's restructure), and three new tests (8, 9, 10),
confirmed with the `apply_tests::a_row_dropped_by_a_regroup_does_
not_outlive_itself_in_selection` test passing (it exercises exactly
finding 1's shape: build a real `TranscriptScreen`, force the same
regroup `diff_tests` already covers, `apply`, then a surviving
row's `begin` -- panics pre-fix, per the review's own test-8 ask).
`docs/IRIS.md`'s 2026-09-05 entry gained the line the review's
"Docs" section asked for. See `docs/REVIEW-2026-09-06.md`'s own "Fixed, 2026-09-06"
section for the per-finding account. Committed together with the
review file.
- [ ] **Iris's 11:39 phone report on the 02:07 build** (four items,
verbatim in `IRIS_TODO.md`'s "From the phone, 2026-09-06, 11:39"):
composer floating two thirds down the screen at launch with black