Current as of PR #11's fourth review, which is deliberately unread: the first instruction is to fetch it. Records what #11 became over three rounds of review, since that shape is what the new review is about, and where the headless rig actually lives, since a rendering claim cannot be verified without it. Drops the finished detail -- PR #10's contents, the source-history archaeology that has been consumed -- and points at the machine-wide pre-submit-review gate rather than restating it.
211 lines
9.7 KiB
Markdown
211 lines
9.7 KiB
Markdown
# Iris extraction handoff
|
|
|
|
Operational handoff for pulling Iris out of ai-app into a standalone framework.
|
|
Not a decisions log; delete it when the extraction is done.
|
|
|
|
## Read this first
|
|
|
|
**Pull request #11 was reviewed on 2026-09-13 and the review has not been read.**
|
|
The session that got it was asked to write this document and stop rather than
|
|
spend context on it. So the first thing to do is read it:
|
|
|
|
```sh
|
|
TOKEN=$(cat ~/.config/gitea/token)
|
|
curl -s -H "Authorization: token $TOKEN" \
|
|
https://git.arirex.me/api/v1/repos/iris/iris/pulls/11/reviews
|
|
curl -s -H "Authorization: token $TOKEN" \
|
|
https://git.arirex.me/api/v1/repos/iris/iris/pulls/11/reviews/<id>/comments
|
|
curl -s -H "Authorization: token $TOKEN" \
|
|
https://git.arirex.me/api/v1/repos/iris/iris/issues/11/comments
|
|
```
|
|
|
|
Three rounds of review had already landed on #11 before this one, so check the
|
|
newest `submitted_at` rather than assuming the first result is current. My
|
|
replies to the earlier rounds are ordinary issue comments on the same PR and
|
|
say what each change was for.
|
|
|
|
## Stop point
|
|
|
|
- Canonical Iris: `git@git.arirex.me:iris/iris.git`, `main` at `0f6a28b`
|
|
(the squash merge of #10).
|
|
- Agent fork: `git@git.arirex.me:iris-ai/iris.git`. The bot cannot push
|
|
canonical; work in the fork and open PRs into `iris/iris:main`.
|
|
- **#11** `split/11-texture-bindings`, worktree `/home/bob/repos/iris-pr11`,
|
|
head `7b318e3`, eight commits on top of `0f6a28b`. Reviewed four times;
|
|
the fourth is unread.
|
|
- **#12** `split/12-pointer-routing`, worktree `/home/bob/repos/iris-pr12`,
|
|
head `028521b`. A scroll falling through a hovered button. Not reviewed as
|
|
of the last check. Independent of #11 and can merge in either order.
|
|
- `/home/bob/repos/ai-app-2` is on `rustify`, worktree clean.
|
|
|
|
## What #11 became
|
|
|
|
It started as "draw the glyph atlas as an array texture" and the review turned
|
|
it into a rework of how primitives are drawn. Worth knowing before reading the
|
|
new review, because the earlier rounds are what produced this shape:
|
|
|
|
- **Atlas pages are their own thing.** `GlyphAtlas` owns its page images and
|
|
emits dirty rectangles; `GpuPages` owns the array texture they upload to.
|
|
`Textures` holds standalone images only.
|
|
- **Every primitive is a registration.** `PrimitiveRegistry::register::<P>`
|
|
takes the primitive's WGSL and what it samples, and returns a
|
|
`PrimitiveKind<P>`. Its list, free list, buffers, bind group layout and
|
|
pipeline all follow from that. Rect, glyph and texture are registered the
|
|
same way at startup, so a caller registering their own primitive with their
|
|
own shader takes the identical path. That is deliberate — the owner wants
|
|
custom user shaders later.
|
|
- **Nothing dispatches dynamically.** Push, free, renumber, upload and draw are
|
|
identical for every primitive; only the entry size and the pipeline differ,
|
|
and those are data. `InstanceList` carries a runtime stride and its data as
|
|
bytes. Measured: 0.2ns per write over a statically typed list, against 1.6ns
|
|
for a trait object.
|
|
- **`shader.wgsl` became `shader/prelude.wgsl` plus one file per primitive**,
|
|
because one module cannot declare two types at the same binding. The prelude
|
|
carries the window, masks, sampled texture, vertex shader and `masked()`.
|
|
- **Within a layer, types draw in registration order** — rect under glyph under
|
|
texture. Order within a layer was never meaningful (freeing an instance
|
|
swaps another into its place), and layers are the compositing mechanism.
|
|
|
|
## Standing instructions from the owner
|
|
|
|
- Pull Iris out even if the Rust application switchover is not accepted. No
|
|
app, session, transcript, setup or server concepts in Iris; the dependency
|
|
runs one way from `app/` to Iris.
|
|
- **Small, coherent PRs.** The original extraction PR was too large to review.
|
|
A slice may be redone rather than transplanted, and need not remove every old
|
|
feature. Independent PRs may be open at once so work continues during review.
|
|
- Do not recreate an `ai` branch in canonical Iris; the fork is the boundary.
|
|
- **Never rewrite a pushed branch.** Follow review with additive commits.
|
|
- Respond to each review finding with a fix or a concise explanation. Do not
|
|
add a ceremonial comment when the changed code already answers it.
|
|
|
|
## The review gate
|
|
|
|
`~/.claude/MACHINE.md` now carries a machine-wide rule, and the procedure is
|
|
the installed **`pre-submit-review`** skill. It is not optional and not
|
|
project-specific: build clean, review the code, review the comments separately
|
|
once the code has settled, then verify the claim by running it. The fixes a
|
|
review produces are themselves unreviewed code, so the passes repeat until a
|
|
round finds nothing.
|
|
|
|
Running it on #11 found four defects that format, clippy, tests and five
|
|
headless renders had all passed — including one hidden *by* the tests passing,
|
|
where an image alone in a layer failed GPU validation because every other case
|
|
happened to have a rectangle in the same layer leaving a bind group set. That
|
|
is the shape to hunt for.
|
|
|
|
`audit.sh` in the skill directory prints every comment line a branch adds
|
|
against a base ref, for an explicit verdict each. The owner's standing
|
|
complaint is verbose agent comments; the default verdict is delete.
|
|
|
|
## Repository topology
|
|
|
|
### ai-app checkout
|
|
|
|
- `/home/bob/repos/ai-app-2`, `origin = git@git.arirex.me:iris/ai-app.git`,
|
|
branch `rustify`.
|
|
- `iris/` is a submodule pinned at `32f6ad8`, the complete extracted snapshot,
|
|
and `.gitmodules` points at the **bot fork**, not canonical Iris.
|
|
- Do not change either casually: ai-app needs the complete snapshot while
|
|
canonical Iris is only partly caught up. Reconcile when canonical contains
|
|
what ai-app needs, or when the owner accepts a temporarily non-building pin.
|
|
|
|
### standalone Iris checkout
|
|
|
|
- `/home/bob/repos/iris`, `origin` = fork, `upstream` = canonical.
|
|
- Fork `main` and `origin/archive/full-extraction` both name `32f6ad8`, the
|
|
target snapshot. `history/full` names the source-history result `a615bcd`.
|
|
- **Do not reset, overwrite or force-push fork `main`**: it is both the target
|
|
reference and the commit ai-app pins.
|
|
- Start each new branch from current `upstream/main` in its own worktree:
|
|
|
|
```sh
|
|
cd /home/bob/repos/iris && git fetch upstream
|
|
git worktree add -b split/13-name /home/bob/repos/iris-pr13 upstream/main
|
|
```
|
|
|
|
The other `/home/bob/repos/iris-pr*` worktrees hold merged branches. They are
|
|
readable references; do not build new work on them.
|
|
|
|
## Merged so far
|
|
|
|
| PR | On canonical `main` |
|
|
| --- | --- |
|
|
| #2 | Build on the current nightly (`4275314`) |
|
|
| #3 | Request a frame after resize (`936fbdd`) |
|
|
| #4 | Decouple `iris-core` from winit (`465e430`) |
|
|
| #5 | Use vsync by default (`ec2b5d4`) |
|
|
| #6 | Notify winit before presenting (`db9b0f2`) |
|
|
| #7 | Keep unsafe reference helpers internal (`0191f20`) |
|
|
| #8 | Initialize the window uniform from the surface (`6e271e8`) |
|
|
| #9 | Preserve primitive-count recursion (`b90c855`) |
|
|
| #10 | Text layout and rendering on Parley (`0f6a28b`) |
|
|
|
|
URLs are `https://git.arirex.me/iris/iris/pulls/{number}`.
|
|
|
|
## Choosing the next slice
|
|
|
|
```sh
|
|
cd /home/bob/repos/iris && git fetch upstream
|
|
git diff --stat upstream/main..archive/full-extraction
|
|
```
|
|
|
|
The archive is a reference, not a patch to apply. Recreate a change on top of
|
|
canonical `main`, leave app-specific behaviour out, and verify it independently.
|
|
Pick disjoint path sets when two PRs are open, and branch each from the latest
|
|
`upstream/main` rather than stacking.
|
|
|
|
Still in the target and not yet claimed:
|
|
|
|
- Widget draw size and measurement cleanup (source commit `6671194`).
|
|
- Retained span, scrolling and layout placement.
|
|
- Retained paints, selection, overlays and shared UI runtime state.
|
|
- Generic desktop/Android framework hosts and reusable example/APK tooling.
|
|
- Application-owned fonts and application-named font families.
|
|
- Shared resource-handle bookkeeping and replaceable glyph-atlas buckets.
|
|
- Positioned text overflow and cluster-safe ellipsis.
|
|
- **The headless rig** — `scripts/run-headless.sh`, `headless.conf` and
|
|
`rig-input` live in ai-app's iris submodule and not in canonical Iris.
|
|
Everything below depends on running them from there; extracting them is a
|
|
slice of its own.
|
|
|
|
## Verifying a framework slice
|
|
|
|
```sh
|
|
cd <iris-worktree>
|
|
cargo fmt --all --check
|
|
cargo clippy --all-targets -- -D warnings
|
|
cargo test
|
|
```
|
|
|
|
`--workspace` when the slice crosses workspace crates. A rendering claim needs
|
|
a real run, which on this machine means the headless rig in ai-app's submodule:
|
|
|
|
```sh
|
|
cd /home/bob/repos/ai-app-2/iris
|
|
./scripts/run-headless.sh tabs --dir /home/bob/repos/iris-prNN \
|
|
--shot /tmp/out.png --seconds 3
|
|
./scripts/run-headless.sh tabs --dir ... --replay /tmp/taps.touch --shot ...
|
|
```
|
|
|
|
A `.touch` file is `<ms> down|move|up <x> <y>` in the output's own pixels; the
|
|
script replays it through a virtual pointer. The `tabs` example's five tabs sit
|
|
at x = 192, 576, 960, 1344 and 1728 on a 1920x1200 output. Read the
|
|
`this-machine-graphics` skill before trusting any of it — the Vulkan device
|
|
here comes and goes, and everything silently falls back to software when it
|
|
does.
|
|
|
|
## Cautions
|
|
|
|
- Read `/home/bob/repos/ai-app-2/AGENTS.md` and the machine-wide rules first.
|
|
- Keep Iris generic: session drivers, transcripts, setup and server concepts,
|
|
app icons and product fonts stay in ai-app. Android and desktop code is Iris
|
|
work only when it is a generic host or platform integration.
|
|
- Preserve the dirty-worktree rule. All worktrees were clean at handoff;
|
|
anything found later may be the owner's or another agent's.
|
|
- Do not delete the archived snapshot or the fork `main` ai-app pins.
|
|
- A complete target branch is not permission to recreate the giant PR.
|
|
- Another agent was freeing disk on this VM and removed `target/` from the
|
|
`iris-pr*` worktrees once. Sources and git state were untouched. Tell peers
|
|
before changing shared machine tooling, and expect a cold rebuild sometimes.
|