RUST.md, DECISIONS.md, IRIS_TODO.md: the port plan, P1-P7, after iris-over-Masonry
Adds "The port, in order (decided 2026-09-05)" to RUST.md: seven ordered steps building the app on iris now that the framework is decided, each naming the Kotlin files it replaces, the client-core pieces it needs (and which are not yet covered and must be ported first), the missing iris widgets it needs (recorded in IRIS_TODO.md's new "Build (for the port)" section), and a pass condition a later agent can run. Ordered by risk to the daily-use path: session screen parity, then the shell merge and a real phone install, then root tabs, the file explorer, settings/enrolment, desktop parity, and the cutover itself. Crate-shape decision recorded in DECISIONS.md: one UI crate, app-ui, grown out of transcript-ui rather than started beside it, with desktop-app/android-app as thin entry points over it and platform-only code staying in the E3/E5 Java shell. Updates RUST.md's "Where things stand" and "For the next agent" to point at P1 rather than the now-closed framework decision. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
621f08d725
commit
5b7dc0e4e2
3 files changed
+298
-4
No files matched your search
@@ -7,6 +7,28 @@ marked **DEFERRED** are ones the agent chose not to decide alone.
|
|||||||
|
|
||||||
## 2026-09-05
|
## 2026-09-05
|
||||||
|
|
||||||
|
- **The rest of the port is one UI crate, `iris/app-ui`, grown out of
|
||||||
|
`iris/transcript-ui` rather than started beside it.** It holds a
|
||||||
|
`Screen` enum plus a back stack — the Rust equivalent of `AppRoot.kt`'s
|
||||||
|
`when` — and `iris/desktop-app`/`iris/android-app` become thin entry
|
||||||
|
points over it. Chosen over a fresh crate because `transcript-ui`
|
||||||
|
already has the right generic shape (`Rsc: HasEvents` +
|
||||||
|
`Rsc::State: FocusHost`) and the `client-core`/`event-model` path
|
||||||
|
dependencies every later screen needs, so growing it in place is the
|
||||||
|
smaller diff. Platform-only code (notification service, share target,
|
||||||
|
QR scanner, Keystore token, deep-link enrolment) stays in the E3/E5
|
||||||
|
Java shell (`android-shell/` + `app/shellApp`) rather than moving into
|
||||||
|
this crate, since none of it is a screen. The Android APK is built by
|
||||||
|
`cargo xtask apk` (E5), merging the app-ui cdylib into the E3 shell so
|
||||||
|
there is one app rather than a demo shell plus a service shell.
|
||||||
|
`app/androidApp` (the Compose app) stays untouched and is the baseline
|
||||||
|
every step is measured against, until parity is reached (P7 decides
|
||||||
|
the switch, and is itself a load-bearing decision left to Iris). Order
|
||||||
|
is by risk to the daily-use path: session screen first (P1, where
|
||||||
|
every hard behaviour already lives), then the shell merge and a real
|
||||||
|
phone install (P2), then root tabs (P3), the explorer (P4),
|
||||||
|
settings/enrolment (P5), desktop parity (P6), and the cutover itself
|
||||||
|
(P7). Full plan: RUST.md's "The port, in order (decided 2026-09-05)".
|
||||||
- **iris gets its own measured frame report, rather than waiting on a
|
- **iris gets its own measured frame report, rather than waiting on a
|
||||||
`dumpsys`/`gfxinfo` answer that cannot see a `SurfaceView`'s GPU-drawn
|
`dumpsys`/`gfxinfo` answer that cannot see a `SurfaceView`'s GPU-drawn
|
||||||
frames.** `iris_core::FrameReport` (`iris/core/src/render/frame_report.rs`)
|
frames.** `iris_core::FrameReport` (`iris/core/src/render/frame_report.rs`)
|
||||||
|
|||||||
@@ -292,6 +292,42 @@ order and what "done" looks like. Tick and date them in place.
|
|||||||
everything, the same way input is**. Whatever the mechanism, a widget
|
everything, the same way input is**. Whatever the mechanism, a widget
|
||||||
that does not animate must pay nothing and import nothing for it.
|
that does not animate must pay nothing and import nothing for it.
|
||||||
|
|
||||||
|
## Build (for the port)
|
||||||
|
|
||||||
|
Widgets `RUST.md`'s "The port, in order (decided 2026-09-05)" needs and
|
||||||
|
iris does not have yet, one entry per gap, named against the P-step that
|
||||||
|
first needs it. Move an entry up to "Fix" or tick it in place once built;
|
||||||
|
do not duplicate it there.
|
||||||
|
|
||||||
|
- [ ] **A history-paging cushion measured in on-screen viewports, not a
|
||||||
|
row count.** (**P1**.) `iris::widget::List` has no equivalent of the
|
||||||
|
Compose app's `HISTORY_SCREENS` — AGENTS.md's "Things that have
|
||||||
|
bitten" is explicit that a fixed row count under-fills a screen on a
|
||||||
|
tool-heavy transcript and over-fills one on a text-heavy one, so
|
||||||
|
whatever loads the next page has to ask the list how many viewports
|
||||||
|
are actually on screen, not assume a constant.
|
||||||
|
- [ ] **A scaled thumbnail/image widget for an in-transcript image.**
|
||||||
|
(**P1**.) `SessionImage.kt`'s bitmap decode-and-downscale has no iris
|
||||||
|
counterpart; iris's own image widget (used by `bench_images.rs`) draws
|
||||||
|
a loaded texture but does nothing about sourcing or scaling one from a
|
||||||
|
server-produced attachment.
|
||||||
|
- [ ] **A modal/dialog primitive.** (**P1**, reused by **P3** and
|
||||||
|
**P5**.) Needed for the session settings dialog, `UsageDialog`'s
|
||||||
|
equivalent, and the delete-with-`deleteForeign` confirmation with its
|
||||||
|
toggle switch. Build once, wherever it is first needed, rather than
|
||||||
|
once per screen that wants one.
|
||||||
|
- [ ] **A horizontal gauge/bar widget.** (**P1**.) For
|
||||||
|
`SessionUsageBar`'s equivalent — a bounded fill reflecting a fraction,
|
||||||
|
nothing fancier.
|
||||||
|
- [ ] **A `BusyItem` equivalent: a dimmed row carrying an operation
|
||||||
|
label that does not block its list's own scroll/drag.** (**P3**.) The
|
||||||
|
Compose version tried an overlay first and it swallowed the drag along
|
||||||
|
with the tap (AGENTS.md's "Shared appearance") — worth not repeating
|
||||||
|
that attempt in iris before building the row-level version directly.
|
||||||
|
- [ ] **A toggle switch.** (**P3**.) For the delete dialog's
|
||||||
|
`deleteForeign` control; iris has no switch/checkbox widget yet as far
|
||||||
|
as this pass found.
|
||||||
|
|
||||||
## Reconsider
|
## Reconsider
|
||||||
|
|
||||||
- [ ] **`WidgetView`.** Iris is unsure of it: what she wants is an easy way
|
- [ ] **`WidgetView`.** Iris is unsure of it: what she wants is an easy way
|
||||||
|
|||||||
+240
-4
@@ -40,6 +40,12 @@ session spending an afternoon on them again.
|
|||||||
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 —
|
||||||
a new ordered list is the next thing to write into this file.
|
a new ordered list is the next thing to write into this file.
|
||||||
|
- **The port plan exists, 2026-09-05: "## The port, in order (decided
|
||||||
|
2026-09-05)"**, seven steps (P1–P7) below "Experiments, in order,"
|
||||||
|
ordered by risk to the daily-use path rather than by screen count. **P1
|
||||||
|
— session screen parity — is next.** One crate decision made there:
|
||||||
|
screens grow out of `iris/transcript-ui` into `iris/app-ui`, with
|
||||||
|
`desktop-app`/`android-app` as thin entry points over it.
|
||||||
- **I5 is now `[x]`: a clean, single-session, like-for-like 24-swipe
|
- **I5 is now `[x]`: a clean, single-session, like-for-like 24-swipe
|
||||||
scroll comparison between Compose and iris exists, 2026-09-05.** Same
|
scroll comparison between Compose and iris exists, 2026-09-05.** Same
|
||||||
sandbox session content for both apps, same emulator, `EMU_GPU=software`
|
sandbox session content for both apps, same emulator, `EMU_GPU=software`
|
||||||
@@ -3195,6 +3201,236 @@ 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.
|
||||||
|
|
||||||
|
## The port, in order (decided 2026-09-05)
|
||||||
|
|
||||||
|
Iris decided iris over Masonry (`DECISIONS.md`). This is the ordered plan
|
||||||
|
for the rest of the app, decided by the design agent per the standing
|
||||||
|
"decide technical questions yourself" instruction — a serious
|
||||||
|
user-facing tradeoff is not in play in the ordering itself, so it is not
|
||||||
|
deferred to her. **Crate shape, decided here**: the screens live in one
|
||||||
|
crate, **`iris/app-ui`**, grown from `iris/transcript-ui` rather than
|
||||||
|
started beside it — `transcript-ui` already has the right generic shape
|
||||||
|
(`Rsc: HasEvents` + `Rsc::State: FocusHost`, the same axis `tabs-ui`
|
||||||
|
varies along) and the same `client-core`/`event-model` path
|
||||||
|
dependencies every later screen needs, so growing it in place is a
|
||||||
|
rename plus new modules rather than a second crate re-declaring
|
||||||
|
dependencies the first already has. It holds a `Screen` enum and a back
|
||||||
|
stack — the direct equivalent of `AppRoot.kt`'s `when` and `MainScreen.kt`'s
|
||||||
|
tab `enum` — with each Compose screen becoming one `iris::widget`
|
||||||
|
subtree module. `iris/desktop-app` (E4) and `iris/android-app` (I2/I5)
|
||||||
|
become thin entry points that call into `app-ui`, the way `AppRoot`/
|
||||||
|
`MainActivity` today call into Compose screens they don't otherwise own.
|
||||||
|
Platform-only code (the notification foreground service, the share
|
||||||
|
target, the QR scanner, the Keystore-sealed token, deep-link enrolment)
|
||||||
|
stays exactly where E3/E5 already put it — `android-shell/` and
|
||||||
|
`app/shellApp` — since none of it is a screen `app-ui` could draw.
|
||||||
|
|
||||||
|
Order is by **risk to the daily-use path**, not by screen count: the
|
||||||
|
session screen is what the app is for and where every hard behaviour
|
||||||
|
(paging, cache, keyboard insets, selection) already lives, so it goes
|
||||||
|
first and on the phone as reachable code as soon as possible, before the
|
||||||
|
lower-risk screens.
|
||||||
|
|
||||||
|
Every step below assumes the `app/ui-sandbox.sh` fixtures (AGENTS.md's
|
||||||
|
"The rigs") and the `this-machine-android` skill's facts (per-checkout
|
||||||
|
AVD, `ui-trace` by accessibility name, GrapheneOS phone quirks, the
|
||||||
|
`adb shell` quoting traps) apply unchanged — read that skill before
|
||||||
|
running any pass condition below that touches an emulator or a real
|
||||||
|
device.
|
||||||
|
|
||||||
|
- [ ] **P1 — session screen parity.** History paging backward (with the
|
||||||
|
page-boundary healing `client-core` does not have yet, below),
|
||||||
|
`TranscriptSource`-backed cache/server stitching, jump-to-latest,
|
||||||
|
tool-call cards and grouping, the session settings dialog, composer
|
||||||
|
attachments, and the keyboard/insets behaviours AGENTS.md's "Things
|
||||||
|
that have bitten" names (the floating-composer bug, `adjustResize`,
|
||||||
|
the `imePadding`-vs-raw-inset rule). This is the highest-risk step:
|
||||||
|
it is the screen the app is used for, every hour of the day.
|
||||||
|
|
||||||
|
**Kotlin it replaces**: `SessionScreen.kt`, `TranscriptList.kt`,
|
||||||
|
`SessionSettingsDialog.kt`, `ToolInput.kt`, `ToolRows.kt`,
|
||||||
|
`AskQuestion.kt`, `Compaction.kt`, `SessionUsageBar.kt`,
|
||||||
|
`PendingAttachments.kt`, `Attachment.kt`, `Attachments.kt`,
|
||||||
|
`SessionImage.kt`, `MemoryNote.kt`, `PeerMessage.kt`, `RawBlock.kt`,
|
||||||
|
`CodeFence.kt`, `MarkdownLinks.kt`, `MarkdownPieces.kt`,
|
||||||
|
`Markdown.kt`, `Bubble.kt`, `ScrollAnchor.kt`, `Drafts.kt`,
|
||||||
|
`UsageDialog.kt`, `Chevron.kt`, `Dividers.kt`. (`transcript-ui`
|
||||||
|
already covers the row/markdown/selection/composer core these sit
|
||||||
|
on top of or beside.)
|
||||||
|
|
||||||
|
**`client-core` needed, and what is not yet covered and must be
|
||||||
|
ported first** (`CLIENT_CORE.md`): `TranscriptSource.kt` (deciding
|
||||||
|
cache vs. server per page and stitching them — "not started"),
|
||||||
|
`TranscriptItems.kt`'s `joinPages`/`healSplitMessage`/`adoptRun`
|
||||||
|
(page-boundary healing — "not ported," and paging backward is
|
||||||
|
exactly what exercises it), the markdown *block* model beyond
|
||||||
|
syntax spans (headings/lists/tables/fences as distinct nodes —
|
||||||
|
"not started," needed for `CodeFence`/`MarkdownPieces`' equivalents),
|
||||||
|
and the attachments route (`/sessions/{id}/attachments` — "not
|
||||||
|
covered" in `api.rs`, needed for `PendingAttachments`/`Attachment`).
|
||||||
|
|
||||||
|
**iris widgets missing, → `IRIS_TODO.md`'s new "Build (for the
|
||||||
|
port)" section**: row-level accessibility names and the tappable
|
||||||
|
link / background-chip primitive (both already listed under I5's
|
||||||
|
leftovers — this step is what needs them, not a new ask); a
|
||||||
|
history-paging cushion measured in on-screen viewports rather than
|
||||||
|
a row count (the `HISTORY_SCREENS` lesson in "Things that have
|
||||||
|
bitten," which iris's `List` has no equivalent of yet); a scaled
|
||||||
|
thumbnail/image widget for `SessionImage`'s in-transcript images; a
|
||||||
|
modal/dialog primitive for the session settings dialog and
|
||||||
|
`UsageDialog` (iris has none today — check before building a second
|
||||||
|
one for P3/P5); a horizontal gauge/bar widget for
|
||||||
|
`SessionUsageBar`.
|
||||||
|
|
||||||
|
**Pass condition**: `app/ui-sandbox.sh`'s fixtures driven by
|
||||||
|
`ui-trace record --do "tap '<label>'"` — a session with the big
|
||||||
|
transcript (`AI_SANDBOX_BIG_MB`), a paused/slow-spawning one
|
||||||
|
(`AI_SANDBOX_SPAWN_DELAY`), and `--delay` on the server — exercising
|
||||||
|
the four states UI_RULES.md says to design first: unknown (a page
|
||||||
|
that hasn't loaded), empty (a session with no messages yet), error
|
||||||
|
(a failed send/interrupt), and too-long (the big transcript,
|
||||||
|
paged). Re-take the I5 `FrameReport` (`iris frame report` in
|
||||||
|
logcat, same as I5's box) once this screen has real paging and
|
||||||
|
compare it against I5's own numbers, not against Compose's — the
|
||||||
|
three measurement sources still are not comparable per
|
||||||
|
`DECISIONS.md`'s DEFERRED item.
|
||||||
|
|
||||||
|
- [ ] **P2 — the shell merge and a real phone install.** Merge this
|
||||||
|
screen's cdylib into the E3/E5 shell (`android-shell` +
|
||||||
|
`app/shellApp`) behind the same feature-flag pattern I5 used to
|
||||||
|
extend `iris-android-app` (`DECISIONS.md`, 2026-09-05), so there is
|
||||||
|
one app — notification service, share target and the real screen —
|
||||||
|
rather than a demo shell and a service shell side by side. Package
|
||||||
|
with `cargo xtask apk` (E5) and get it onto the real GrapheneOS
|
||||||
|
phone, not just the emulator: `arm64-v8a` is the ABI that matters
|
||||||
|
there (the emulator here is x86_64), and the `this-machine-android`
|
||||||
|
skill's facts apply for the first time in this port — no System
|
||||||
|
Tracing on that phone (frame numbers have to come from `FrameReport`
|
||||||
|
itself), the local-network permission is required there even though
|
||||||
|
AOSP's docs say VPN traffic is excluded, and `ui-trace`/`adb`
|
||||||
|
target this checkout's own emulator by default so a real-device
|
||||||
|
command needs `-s <serial>` explicitly.
|
||||||
|
|
||||||
|
**Kotlin it replaces**: nothing further than E3 already did
|
||||||
|
(`Notifications.kt` → `notifications.rs`, `Share.kt` → `share.rs`,
|
||||||
|
`ServerConfig.kt`'s Keystore half → JNI calls into `wg-app-link`) —
|
||||||
|
this step is wiring P1's screen in as the shell's real content
|
||||||
|
instead of E3's placeholder, plus getting a signed APK onto a
|
||||||
|
physical device for the first time in this port.
|
||||||
|
|
||||||
|
**`client-core` needed**: none new; E3 already covers what the
|
||||||
|
shell itself needs. Attachments (P1's gap) matter here too if a
|
||||||
|
real photo share is exercised.
|
||||||
|
|
||||||
|
**iris widgets missing**: none — this step is integration, not new
|
||||||
|
widgets.
|
||||||
|
|
||||||
|
**Pass condition**: `cargo xtask apk`, install on the real phone
|
||||||
|
over adb, enroll via the deep link, background the app and get a
|
||||||
|
real notification, share a text snippet into a session, and
|
||||||
|
confirm `ui-trace` can still find controls by name on real
|
||||||
|
hardware (accessibility names are not guaranteed to survive a real
|
||||||
|
device's TalkBack/AccessKit wiring the way they do in the
|
||||||
|
emulator — this is the first time that gets checked for real).
|
||||||
|
|
||||||
|
- [ ] **P3 — root tabs.** `Screen`/`MainTab` in `app-ui`: the sessions
|
||||||
|
list, import, models and setups tabs, plus spawn and the app's one
|
||||||
|
level of back-stack navigation (`AppRoot.kt`'s `when`).
|
||||||
|
|
||||||
|
**Kotlin it replaces**: `AppRoot.kt`, `MainScreen.kt`,
|
||||||
|
`SessionListScreen.kt`, `ImportScreen.kt`, `ModelsScreen.kt`,
|
||||||
|
`SetupsScreen.kt`, `SpawnScreen.kt`, `BusyItem.kt`,
|
||||||
|
`UniqueItems.kt`, `SessionAlerts.kt`.
|
||||||
|
|
||||||
|
**`client-core` needed, not yet covered**: setups/machine/provider
|
||||||
|
discovery, the models routes (`/models*`, HuggingFace browsing and
|
||||||
|
downloads), and importing (`/setups/{id}/importable*`) — all three
|
||||||
|
listed "not covered" in `api.rs`'s table and none started; each is
|
||||||
|
real work, not a stub, per `CLIENT_CORE.md`'s own caveat.
|
||||||
|
|
||||||
|
**iris widgets missing**: a `BusyItem` equivalent — a row dimmed,
|
||||||
|
drained of colour, labelled with the operation in progress, that
|
||||||
|
does **not** block the list's own scroll/drag the way an overlay
|
||||||
|
did on the Compose side (AGENTS.md's "Shared appearance"); a
|
||||||
|
`uniqueItems` equivalent is logic, not a widget, and ports directly
|
||||||
|
into `app-ui` itself; a confirmation dialog with a toggle switch,
|
||||||
|
for the delete-with-`deleteForeign` flow, needs the same modal
|
||||||
|
primitive P1 flagged — build it once, here or in P1, whichever
|
||||||
|
lands first.
|
||||||
|
|
||||||
|
**Pass condition**: `ui-trace` tap-by-name on all four tabs against
|
||||||
|
`ui-sandbox.sh`'s fixtures; the two-copies-of-one-session-id
|
||||||
|
fixture (AGENTS.md's "Importing") does not crash the list — this is
|
||||||
|
the regression `uniqueItems` exists for and it must be exercised
|
||||||
|
here, not assumed; the delete dialog's paragraph reads correctly
|
||||||
|
both with and without `deleteForeign` toggled (its own text, not
|
||||||
|
appended, per AGENTS.md).
|
||||||
|
|
||||||
|
- [ ] **P4 — file explorer.** The viewer, the editor with its
|
||||||
|
`EDIT_LIMIT`, and the 409 conflict.
|
||||||
|
|
||||||
|
**Kotlin it replaces**: `FilesScreen.kt`, `FileViewer.kt`,
|
||||||
|
`FileEditor.kt`, `FileLines.kt`.
|
||||||
|
|
||||||
|
**`client-core` needed, not yet covered**: `/setups/{id}/dir|file`
|
||||||
|
— not in `api.rs`'s covered list, real work, port first.
|
||||||
|
|
||||||
|
**iris widgets missing**: nothing beyond what P1 needs (a
|
||||||
|
virtualised line-numbered text view is `iris::widget::List` reused,
|
||||||
|
per I3's box) — the open question is whether the editor's
|
||||||
|
`BasicTextField`-equivalent cost (`docs/EXPLORER.md`'s "what the
|
||||||
|
measurements said") reproduces in iris's `TextEdit` at the same
|
||||||
|
`EDIT_LIMIT`, which this step has to re-measure rather than assume.
|
||||||
|
|
||||||
|
**Pass condition**: `app/ui-sandbox.sh`'s `~/files` fixture tree
|
||||||
|
(empty dir, tab/apostrophe names, binary, over `FILE_LIMIT`,
|
||||||
|
`chmod 000`, symlinks good and broken, one source file per
|
||||||
|
language, `edit-32k.rs`/`edit-128k.rs`/`big-source.rs`) driven by
|
||||||
|
name; the 409 reproduced by editing the file on the machine between
|
||||||
|
opening it and saving, per AGENTS.md's own recipe.
|
||||||
|
|
||||||
|
- [ ] **P5 — settings, enrollment, notifications permission.**
|
||||||
|
|
||||||
|
**Kotlin it replaces**: `SettingsScreen.kt`, `ServerConfig.kt`'s
|
||||||
|
remaining non-Keystore parts, `DebugStats.kt`, `FrameStats.kt`,
|
||||||
|
`CrashLog.kt`. The QR scanner (`EnrollmentScanActivity`, in
|
||||||
|
`wg-app-link`) is platform-only and is **not** replaced — it stays
|
||||||
|
a Java/Kotlin activity per decision 1 above, called into from
|
||||||
|
`app-ui` the way it is called into from Compose today.
|
||||||
|
|
||||||
|
**`client-core` needed**: none new — `config.rs`'s
|
||||||
|
`EnrolledServer`/`parse_link` already cover the deep-link half; the
|
||||||
|
Keystore half stays the JNI call E3 already wired.
|
||||||
|
|
||||||
|
**iris widgets missing**: none identified yet — a plain form screen.
|
||||||
|
|
||||||
|
**Pass condition**: enroll via the same `aiappshell://enroll?...`
|
||||||
|
link `ui-sandbox.sh`'s banner prints; the local-network-not-allowed
|
||||||
|
banner (AGENTS.md's standing-condition text) reads by name when the
|
||||||
|
permission is off; `POST_NOTIFICATIONS` request flow checked on the
|
||||||
|
real phone from P2, not just the emulator.
|
||||||
|
|
||||||
|
- [ ] **P6 — desktop parity.** Root tabs, explorer and settings on
|
||||||
|
`iris/desktop-app`, matching P3–P5 there. Not a Kotlin replacement
|
||||||
|
(the desktop app has no Compose original) — this is closing the
|
||||||
|
gap `E4` deliberately left (session list + transcript only).
|
||||||
|
|
||||||
|
**`client-core` needed**: the same P3/P4 gaps, once closed there.
|
||||||
|
|
||||||
|
**Pass condition**: `run-headless.sh` screenshots of each tab and
|
||||||
|
the explorer against `app/ui-sandbox.sh`, the same way E4's did.
|
||||||
|
|
||||||
|
- [ ] **P7 — the switch of `ai-app`'s main.** Point `ai-app`'s production
|
||||||
|
Android build at `app-ui`/`android-shell` instead of
|
||||||
|
`app/androidApp`; decide then whether `app/androidApp` stays as a
|
||||||
|
reference or is retired — a load-bearing decision (AGENTS.md's
|
||||||
|
"ask before changing load-bearing decisions") to bring to Iris
|
||||||
|
rather than make here.
|
||||||
|
|
||||||
|
**Pass condition**: the full set of pass conditions above, re-run
|
||||||
|
once more against a real `ai-server` (not the sandbox) on a real
|
||||||
|
phone, side by side with the Compose build until it holds.
|
||||||
|
|
||||||
## For the next agent
|
## For the next agent
|
||||||
|
|
||||||
What to do when you pick this up, in order, so nothing here has to be
|
What to do when you pick this up, in order, so nothing here has to be
|
||||||
@@ -3206,10 +3442,10 @@ re-derived:
|
|||||||
2. Work on the **`rustify`** branch of this clone (`ai-app-2`), not on
|
2. Work on the **`rustify`** branch of this clone (`ai-app-2`), not on
|
||||||
`main` and not in `ai-app`. Nothing on this branch is production until
|
`main` and not in `ai-app`. Nothing on this branch is production until
|
||||||
Iris says so. Commit and push as you go.
|
Iris says so. Commit and push as you go.
|
||||||
3. Take the next unchecked box above, in order. E1 has proved android-view
|
3. The E- and I-steps (the framework decision) are done — iris won,
|
||||||
on this emulator, so the E-steps and the I-steps can now proceed in
|
`DECISIONS.md` 2026-09-05. Take the next unchecked P-box in "## The
|
||||||
parallel in separate sessions; see "Where things stand" at the top for
|
port, in order (decided 2026-09-05)"; **P1 — session screen parity —
|
||||||
which is next.
|
is next.**
|
||||||
4. Every step ends with its measurement written into this file beside the
|
4. Every step ends with its measurement written into this file beside the
|
||||||
box, and the box ticked or the reason it could not be written in its
|
box, and the box ticked or the reason it could not be written in its
|
||||||
place. A step that is blocked says by what, not "later". Write it as you
|
place. A step that is blocked says by what, not "later". Write it as you
|
||||||
|
|||||||
Reference in new issue
Block a user