Files
ai-app/TODO.md
T
iris-ai 7278a58387 Settings as a screen with two tabs, and fields that cost one line
The settings dialog had outgrown a dialog: it scrolled inside itself,
covered the session it is about, and had nowhere to put a second tab. It
is a screen now, drawn over the session like the file explorer so the
session under it stays composed, with the back gesture to leave it. The
second tab is ProviderScreen itself -- the same composable the machines
tab opens -- so a provider's settings have two ways in and one
implementation.

Every text field in the app goes through LabelledField: the label is a
line above the box rather than a thing floating inside it, the hint says
what leaving it blank means, and the padding is one line's worth.
Material's outlined field spends the height of three lines to hold one,
which on a form of a dozen settings is a screen and a half of scrolling.
The value's own text is unchanged -- the framing was what cost.

A session also gets a system prompt, which for llama.cpp is one entry in
the params table and no app change: it rides in front of the conversation
on every request rather than being recorded as the first thing in it, so
changing it takes effect on the next message. ParamKind::Prose is new
because a paragraph in a one-line box shows six words of itself.
2026-09-21 03:35:54 -04:00

3.2 KiB

TODO

Working list from Iris, 2026-09-03. Remove an entry when it lands; annotate one in place when it turns out to need a decision.

App — transcript

  • Decide how running background tasks can be inspected. For now the session status shows only the provider-reported count; command details stay in their existing tool cards and must not become subagent cards.

  • Messages received from other agents are inconsistent — sometimes they appear, sometimes they don't. Needs a rig. Read the code rather than measured: a live Claude session only learns of a peer message from the origin object on a turn's result (session/claude/translate.rs), which the CLI attaches to a turn the message started. So a message that arrives mid-turn, or a second one within one turn, has nowhere to be reported — while an imported session, which syncs from the CLI's own file, picks up every one of them. That would show exactly as "sometimes". Confirming it means driving a real stream-json session and sending it messages in both states.

Session settings

  • Autocompact belongs in session settings; empty disables it, which is the default. Iris chose "hand it to the driver" — only where a driver has auto-compaction of its own. That option was offered on a false premise and is not buildable yet. It named pi's set_auto_compaction, but pi was never built as a driver here: session/llama.rs talks to llama-server's OpenAI-compatible endpoint directly, and its compact() refuses outright. Claude Code's auto-compaction is the CLI's own and nothing in the stream-json control protocol this app uses configures it. So the setting would be stored, passed to a driver, refused by every one of them, and the field would never appear on any session. What is needed first is either a driver that can take it, or a different rule — the server watching contextTokens and running /compact itself is the one that would work today, for Claude sessions, and it is the option that was not chosen.

A session the server could not load

  • A session whose transcript will not parse is skipped with nothing but a log line, and from the phone it looks exactly like an idle unresponsive one. SessionManager::new catches a failing launch and logs "couldn't relaunch session ", so the session has no pump and no driver: no status, no history, nothing sendable. That is what the taskNote incident (fd71d87) looked like from Bryan's phone, and why it needed a report from him rather than being visible in the app. Event::Unreadable removes the cause that time, but not the class — an unreadable process.json, a provider edited away and an unreachable host all reach the same place. This is the "design the unknown state first" rule: a session the server could not load is not a session with nothing to say, and only the phone can show the difference. It needs a status the wire can carry for it — the failure with its reason, reported on the session itself — rather than the reader having to tell it apart from silence.