TermFlow Roadmap

Status: 2026-05-01 · Current release: 0.4.0 · Working towards 1.0.

Stages 1–3 are complete. Stage 4 (1.0 stabilisation) is nearly done: §3.2 (sample apps), §3.3 (killer demo, hosted in llm4s), §3.4 (Grid

  • Border layouts), and §3.5 (migration guide — "no migration needed for 0.2.x → 1.0") have all landed, and §4.1 / §4.3 / §4.4 / §4.5 / §4.6 / §4.7 / §4.8 / §4.9 / §4.10 of the pre-1.0 release-hardening checklist are closed. §4.2 (release-doc sweep) is the last open item before cutting v1.0.0-RC1. MiMa (§3.1) was deferred to the post-1.0 cycle (baseline = 1.0.0).

This document is forward-looking: it describes the work left, not the history of the work done.


1. Vision

Pure-FP TUIs for Scala. Deterministic, golden-tested, type-safe — with mouse, themes, and modal dialogs when you need them.

TermFlow's defensible niche is the Elm Architecture done well in Scala: immutable model, pure update, declarative view, async via Cmd/Sub, plus a snapshot test harness no other Scala TUI library offers.

Non-goals

  • A Lanterna port. No mutable widgets, no shared GUI thread, no listener callbacks as the primary event mechanism.
  • A general-purpose toolkit. TermFlow targets interactive CLIs, REPLs, dashboards, installers, chat clients, and admin tools — not full-screen text editors or game engines.
  • Curses parity. Just enough primitives to render and diff correctly.

2. Current state (0.4.0)

What ships today:

  • Five published modulestermflow-terminal / -screen / -app / -widgets plus the umbrella termflow artefact, and termflow-testkit for tests. Maven Central as org.llm4s::*.
  • Elm-style runtimeTuiApp[Model, Msg], Cmd, Sub, RuntimeCtx, 60-fps frame-diffed ANSI renderer with capability downgrade.
  • Capability detection — true-colour / 256-colour / 16-colour / 8-colour / mono, bracketed paste, mouse (SGR-1006), extended modifier parsing, SIGWINCH-driven resize, terminal-attention notifications (iTerm2 OSC 9 / 1337, kitty OSC 99, VTE OSC 777, BEL fallback).
  • 20+ widgetsTextField, MultiLineInput, Button, CheckBox, RadioGroup, Select, Autocomplete, ListView, Table, Tree, Tabs, SplitPane (drag-resize), Separator, ScrollBar, ProgressBar, Spinner, StatusBar, LogView, MenuBar, Form. Plus Layout DSL (Row / Column / Fill / Zone), HitTest[Id], Theme + BorderChars.
  • Seven dialog helpersmessage, confirm, textInput, listSelect, waiting, fileDialog, directoryDialog, actionList.
  • Grapheme-aware text editing — UAX #29 cluster boundaries via BreakIterator, wide-cell math via WCWidth.
  • TestkitTuiTestDriver, KeySim, MouseSim, GoldenSupport. Published as termflow-testkit.
  • ~22 sample apps — counter, async counter, clock, dashboard, echo, hello, forms, wizard, dialog, file-dialog, themes, unicode, stress, sine, hub, input, tabs, task, catalog, widgets, showcase, tree, editor, chat.
  • Docs site — live at https://llm4s.github.io/termflow with Introduction, four tutorials, eight layer guides (including Accessibility), ten cookbook recipes (including the rolling-console / agent-UI walkthrough), a thread-model reference, and aggregated Scaladoc.

No outstanding architectural debts for 1.0. Remaining work is in §3 and the pre-1.0 release-hardening checklist in §4.


3. Stage 4 — Stabilisation (target: 1.0.0)

The lock-in stage. Goal: produce an API stable enough to keep unchanged for years.

3.1 MiMa for binary compatibility — deferred to post-1.0

Originally planned as a 1.0 gate, but moved out of the critical path (decision: 2026-04-30). The simpler workflow is to ship 1.0 first, then wire sbt-mima-plugin against 1.0.0 as the baseline so every subsequent release (1.0.x, 1.1.0, …) is checked.

Why the change:

  • 0.2.0 is already API-stable, so the 0.2.0 → 1.0 filter list would mostly be noise.
  • Avoids the bookkeeping cost of maintaining mimaBinaryIssueFilters during the 0.2.x → 1.0 window.
  • Removes the chicken-and-egg between §3.1 and §3.5 — see §3.5 for the simplified migration-guide stance.

Plan once 1.0 ships:

  1. Add sbt-mima-plugin to project/plugins.sbt.
  2. Set mimaPreviousArtifacts := Set("org.llm4s" %% name % "1.0.0") on each of termflow-terminal, termflow-screen, termflow-app, termflow-widgets, termflow, and termflow-testkit.
  3. Append mimaReportBinaryIssues to the ciCheck alias.

This becomes part of the 1.0.1 / 1.1.0 release prep, not 1.0.

3.2 Sample app catalogue gaps — ☑ landed

All three planned samples shipped (#188 / #189 / #190): tree/ (file-tree explorer over the Tree widget), editor/ (multi-buffer text editor exercising MultiLineInput + SplitPane + MenuBar), and chat/ (streaming chat with scrollback per the streaming-output cookbook recipe). Catalogue now stands at 22 apps.

3.3 Killer demo — ☑ landed

The llm4s streaming chat client shipped at modules/samples/.../chat/tui in the llm4s repo. It exercises the headline TermFlow surface — live streaming via the LogView auto-tail pattern, mouse-wheel scrollback, slash commands (/help, /clear, /theme), light/dark theme toggle, and a pinned bottom prompt — against a real Anthropic-API backend.

Termflow's README now leads with the chat client screenshot (docs/assets/chat-ui-screenshot.png) plus a "Built with TermFlow — source at llm4s/llm4s/.../chat/tui" link, exactly as the §3.6 DoD asks.

The original handover spec (docs/design/chat-tui-demo-spec.md in llm4s) and the implementation plan that grew out of it remain useful reference material; the live source supersedes them as the canonical example.

3.4 GridLayout + BorderLayout — ☑ landed

Shipped in #187. Layout.Grid(columns, rowGap, colGap, cells) with GridCell row/column spans, and Layout.Border(top, left, center, right, bottom) with five-zone resolution. Both flow through Layout.resolveTo so existing resolve callers are unchanged. LayoutGridSpec and LayoutBorderSpec cover sizing, gaps, spans, and zone omission.

3.5 Migration guide

With MiMa deferred (§3.1), there is no automated source of breakage data for 0.2.0 → 1.0. The guide page stays useful as a hand-written record of any deliberate API changes during the run-up to 1.0.

For 1.0:

  • Walk the public API by hand, note any intentional breaks, and write before/after recipes for each.
  • If nothing broke, collapse the page to "no migration needed; 1.0 is source-compatible with 0.2.0."
  • Once §3.1 is wired post-1.0, future entries are driven by MiMa filters as originally intended.

3.6 Definition of done for 1.0

  • ☑ Docs site live at https://llm4s.github.io/termflow.
  • ☑ Tutorial ladder complete (Hello World, Counter, Async, Forms).
  • ☑ Sample app count ≥ 20 (22 today, including tree, editor, chat).
  • Layout.Grid + Layout.Border shipped (§3.4).
  • ☑ Migration guide populated — docs/reference/migration.md carries the explicit "no migration needed for 0.2.x → 1.0" statement plus the additive-changes catalogue (§3.5 / §4.3).
  • ☑ README headline screenshot is the llm4s chat client (§3.3 — demo hosted in llm4s, screenshot + link in this README).
  • ☑ Pre-1.0 release-hardening checklist complete (§4) — interim release-doc sweep at 0.4.0 finished §4.2; the final 0.4.0 → 1.0.0 bump rides with the release PR itself.

MiMa (§3.1) was originally on this list; it is now scheduled for the 1.0.1 / 1.1.0 cycle with 1.0.0 as the baseline.


4. Stage 5 — Pre-1.0 release requirements

Final hardening before tagging v1.0.0. These are not new feature tracks; they are release-quality gates for the current library surface.

4.1 User-visible error path — ☑ landed

Cmd.TermFlowErrorCmd now reaches the user. SimpleANSIRenderer overlays a red, bold banner across the top row of the next frame and clears it on the following render — long messages truncate with an ellipsis. SimpleANSIRendererSpec covers banner content, styling, truncation, and frame immutability. TuiTestDriver.observedErrors gives tests the same assertion path without a real terminal. The app-layer guide has a new "How errors reach the user" section that shows the rendered banner and the testkit hook.

4.2 Version and release-doc sweep — ☑ landed (interim 0.4.0 pass)

Every copy-pasteable coordinate in the published docs has been bumped from 0.2.0 to the current released baseline (0.4.0): README quick- start, all four layer guides, the testkit guide, the install page, the Hello-World tutorial, and the API reference module table. Migration notes acknowledge 0.2.0 / 0.3.0 / 0.4.0 → 1.0 as the no-migration window, and the new reduced-motion entry is catalogued. The roadmap headline now reads Current release: 0.4.0. Release-instructions still describe the v[0-9]* tag path, which already covers v1.0.0.

A second, narrower sweep happens at 1.0 tag time: bump every 0.4.01.0.0, drop the "no migration needed" wrapper from migration.md (or re-cast it as historical), and update the §2 "Current state" heading. That bump is mechanical — same files, same patterns — and is deferred to the release PR rather than landed pre-emptively, so the coordinates always reflect what's actually on Maven Central.

Historical mentions of 0.2.0 / 0.3.0 are kept in places where they describe the migration story (e.g. early-semver examples in the README, the pre-1.0 cycle catalogue in migration.md, 0.2.0 → 1.0 references in §3.5 / §4.7 of this roadmap) — those are intentional and explained in context.

4.3 Public API and docs example audit — ☑ landed

Walked the public-facing APIs and every tutorial / guide / cookbook snippet against the source. Eight signature drifts and dead-code blocks in the docs were corrected (Cmd.asyncResult, Sub.TerminalResize, Cmd.FCmd type params, MultiLineInput.handleKey curried form, Capabilities.notifications, missing RootNode.input arg, mistyped Cmd.FCmd in the file-picker recipe, orphaned Layout.column block in the full-screen-layout recipe). Cmd.RequestAttention and Cmd.Notify are now reflected in the app-layer Cmd table. docs/reference/migration.md is populated with the explicit no-migration-required statement plus a catalogue of additive changes since 0.2.0. mdbook build (with linkcheck) is green. SPI markers on TuiRenderer / CmdConsumer / CmdBus / EventSink / EventSource were already in place; any further Scaladoc polish belongs in §4.8.

4.4 Layout ergonomics audit — ☑ landed

Layout.toBudgetedRootNode(width, height, input) now expresses the deferred form alongside the existing eager toRootNode, putting the layout into RootNode.layout so the renderer resolves it against the frame's full budget at render time. toRootNode keeps its eager semantics; its Scaladoc flags the trap and points at the budgeted form. A new cookbook recipe (full-screen-layout.md) walks the header / fill / footer pattern, the eager-vs-deferred trade-off, and the both-fields composition seam. LayoutSpec covers both forms with a Fill-collapses vs Fill-expands comparison.

4.5 Rolling console / agent UI recipe — ☑ landed

docs/cookbook/rolling-console.md walks the Claude-Code / Cursor-style transcript pattern end-to-end: model shape (Vector[String] buffer + scrollOffset + autoTail), auto-tail logic, key routing (Arrow / PageUp / PageDown / End / Ctrl+C), mouse-wheel scrollback through LogView.scrollDelta, view composition with LogView + an InputNode prompt, and the Layout.Border alternative for resize-clean layouts. The recipe is explicit that TermFlow owns an in-app scrollback viewport inside the alternate buffer; native terminal scrollback is the post-1.0 §5.3 idea, not the default runtime contract. Linked from docs/cookbook/index.md, docs/SUMMARY.md, and the LogView section of the widgets guide. ChatStreamApp (sbt chatDemo) is the live worked example referenced from the recipe.

4.6 Mouse-wheel scrolling for LogView-style views — ☑ landed

LogView.scrollDelta(event, viewport, ticksPerDetent) plus LogView.Viewport(at, width, height) map a MouseEvent.Scroll onto a clamp-friendly scroll delta when the wheel lands inside the viewport, returning None for outside-the-rect or non-scroll events. chatDemo wires it in (3 lines per detent, ignored over prompt / status row). LogViewSpec exercises every helper branch; ChatStreamAppSpec adds two MouseSim.scrollUp tests for the in-pane and out-of-pane paths. The streaming-output cookbook recipe documents the pattern next to the keyboard fallbacks.

4.7 Test coverage review and quick wins — ☑ landed

Because TermFlow is mostly deterministic UI logic, coverage should be higher than a typical terminal integration project. Run sbt --batch coverageLib, inspect the lowest-covered files/branches, and take the low-risk wins before 1.0.

Current local coverage snapshot (2026-04-30, post a971a94):

  • termflow-terminal: 87.79% statements / 90.48% branches.
  • termflow-screen: 90.76% statements / 77.45% branches.
  • termflow-app: 86.99% statements / 81.20% branches.
  • termflow-widgets: 92.69% statements / 85.23% branches.

The coverage-uplift branch (a971a94) lifted termflow-terminal from 66.04% → 87.79% statements (63.32% → 90.48% branches), termflow-screen from 71.81% → 90.76% statements (65.22% → 77.45% branches), and termflow-app from 80.29% → 86.99% statements (68.61% → 81.20% branches). All four published modules are now ≥87% statement coverage, with termflow-terminal and termflow-screen — the §4.7 priority targets — both above 87%.

Acceptance:

  • Add focused tests for pure/render/update logic with obvious gaps.
  • Prefer deterministic tests over brittle real-terminal integration.
  • Record any accepted low-coverage areas with rationale (JLine/raw TTY integration, shutdown-hook paths, genuinely platform-specific code).
  • Keep coverageLib green and ensure the combined trend moves up, with particular attention to termflow-terminal and termflow-screen.

4.8 Zero-warning build and Scaladoc polish — ☑ landed

sbt --batch ciCheck is warning-free across all published modules and the sample/testkit projects.

sbt --batch unidoc is clean of unresolved-link warnings: five Scaladoc [[…]] references that pointed at out-of-scope or unqualified members were corrected — [[InputKey]] / [[InputKey.Tab]] now spell KeyDecoder.InputKey…, Theme.box's [[chars]] / [[border]] references the slot via [[Theme.chars]] / [[Theme.border]], [[Move]] and friends in MouseEvent are qualified as [[MouseEvent.Move]] etc., and TerminalBackend.onResize's JLine Terminal.Signal.WINCH reference dropped its broken [[…]] wrapper (JLine is on the runtime classpath but not a unidoc target). A non-exhaustive match warning in Keymap.renderKey (missing the InputKey.NoOp case) was closed at the same time.

The remaining [warn] Flag -classpath set repeatedly is a structural sbt-unidoc / Scala-3-doctool quirk (the doc invocation receives -classpath once from sbt-unidoc and once from the dotty front-end). It is not an unresolved-link warning and there is no in-tree fix; track upstream if it becomes load-bearing.

mdBook/linkcheck stay green; the docs site builds unchanged.

4.9 Reduced-motion flag — ☑ landed

A TERMFLOW_REDUCED_MOTION=1 env var (and TermFlowConfig field defaulting to it) that disables cosmetic animation: Spinner renders a static frame, indeterminate ProgressBar stops ticking, and apps can read the flag to drop their own animation. Useful for vestibular accessibility, screen-reader environments, and bandwidth-constrained sessions.

Acceptance:

  • Env var honoured at runtime construction.
  • Spinner renders a static frame when the flag is set.
  • Indeterminate ProgressBar ticks slow or become static.
  • Apps can query the flag via RuntimeCtx.
  • Documented in an accessibility.md docs page (also a home for any future a11y notes).

Tracked as #139.

4.10 Thread-model documentation — ☑ landed

A docs/reference/thread-model.md (or a new section in the app-layer guide) explaining the runtime's thread topology — runtime thread, input producer, Sub.Every scheduler, Future executor, CmdBus — and the invariants apps and widget authors can rely on (update / view always run on the runtime thread; Cmd.FCmd continuations return via the bus; Sub callbacks run off their respective threads; don't close over mutable state inside FCmd; don't block the runtime thread).

Doc-only; no code changes. Pairs naturally with §4.5.

Tracked as #134.


5. Stage 6 — Alternative backends and renderers (post-1.0, speculative)

Each backend or renderer is opt-in. None are on the 1.0 critical path.

5.1 Telnet backend

termflow-backend-telnet. Bind a port, accept connections, each connection becomes a TerminalBackend. Telnet option negotiation (NAWS for size, ECHO suppression, binary). Small library; medium effort.

Use case. Self-hosted admin consoles, MUDs, BBS-style apps, oncall debug shells. Not encrypted — operators wrap it in stunnel / WireGuard / SSH-jumphost for production.

5.2 Web backend (xterm.js over WebSocket)

termflow-backend-web. Serve xterm.js plus a WebSocket; the WS frames become the terminal stream. Run a TUI in a browser tab.

Effort. Large but cleanly bounded. Probably the most "wow factor" of the bunch — a Scala TUI in the browser is unique.

5.3 Rolling console renderer

A constrained normal-buffer renderer/runtime mode for agent and command runner apps that want native terminal scrollback: output appends to the terminal's real history while a live prompt/status area remains pinned near the bottom.

This should not try to support arbitrary full-screen TermFlow VDOM. The current default runtime enters the alternate buffer and the default renderer diffs fixed frames by absolute coordinates; native scrollback needs a different contract built around append-only transcript events, prompt repainting, cursor save/restore, and possibly terminal scroll regions.

Use case. Claude Code / Cursor-style agents, build runners, REPLs, and long-running command logs where users expect their terminal emulator's own scrollbar, copy/search behaviour, and shell history context to keep working.

Shape. Likely a dedicated RollingConsoleApp or renderer API, not a flag on SimpleANSIRenderer. It should support bounded app-side history for replay/testing, normal-buffer append, fixed bottom prompt, keyboard input, resize handling, and a graceful fallback when terminals handle scroll regions poorly.

Effort. Medium-large and compatibility-sensitive. Worth prototyping after 1.0, but too risky to make part of the 1.0 contract.

5.4 Explicitly not planned (third-party PRs welcome)

  • Swing / AWT emulator backend — desktop window with a TUI emulator inside. Skipped because §5.2 covers most of the same use cases at similar effort and reaches more users.
  • SSH backend — wrap Apache MINA SSHD or sshj. Skipped because key management, auth, and connection state are a perpetually-supported surface area we don't want to own. Compose §5.1 Telnet behind an external SSH jump host instead.

The TerminalBackend trait stays public so external contributors can ship either as a separate artefact.


6. Open questions

  1. Native image. sbt-native-image build for graalvm-native-image? The shutdown hook + JLine reflection make this non-trivial. Investigate post-1.0.
  2. Cross-publish for Scala 2.13. Already on legacy-213-track. Keep parity through 1.0, then re-evaluate based on adoption.
  3. Resizing semantics. When the terminal shrinks, do we clip or rewrap? Currently clip. The Layout pass makes rewrap cheap if we want to switch.
  4. i18n. Right-to-left text? Bidi? Probably out of scope for 1.0; document as a known limitation.
  5. Accessibility. Screen readers don't really hit a TUI — they read the terminal directly. Worth an "Accessibility notes" docs section before 1.0.
  6. Windows native. Currently relies on JLine for cmd.exe / Windows Terminal. May need a JNA-backed WindowsConsoleBackend if JLine's behaviour proves insufficient.

7. Lanterna comparison reference

The original 0.1.x roadmap was structured around a comparison with Lanterna. That comparison drove Stages 1–3, and almost every Lanterna component now has a TermFlow equivalent (TextFieldTextBox, ListViewActionListBox, SplitPaneSplitPanel, etc.). Two Lanterna things we deliberately don't match:

  • The shared GUI thread / listener-callback event model. Replaced by the Elm-style update loop. Not coming back.
  • Mutable widgets. Replaced by stateless renderers + state on the app's model. Not coming back.

Two TermFlow-only wins worth preserving through 1.0:

  • Golden-snapshot testing (TuiTestDriver + GoldenSupport).
  • HitTest[Id] cache built from the layout pass — Lanterna has no equivalent.

8. Recent decisions (rolling, last ~3 months)

  • 2026-05-01 — Stage 4 §4.2 closed (interim 0.4.0 pass): every copy-pasteable install coordinate in README + layer guides + tutorials + install page + API reference now reads 0.4.0 instead of 0.2.0. Migration notes acknowledge 0.2.0 / 0.3.0 / 0.4.0 → 1.0 as the no-migration window. Roadmap headline + §2 heading + cookbook / guide counts updated to reflect the post-§4.5 / §4.10 / a11y state. The final 0.4.0 → 1.0.0 mechanical bump is deferred to the release PR. With this, §3.6 DoD is complete and 1.0-RC1 is unblocked.
  • 2026-05-01 — Stage 4 §3.3 closed: the llm4s chat client shipped at modules/samples/.../chat/tui in the llm4s repo. Termflow's README now leads with the screenshot (docs/assets/chat-ui-screenshot.png) and links to the source. The §3.6 DoD's "README headline screenshot" box is ticked.
  • 2026-04-30 — Stage 4 §4.5 closed: rolling-console / agent-UI cookbook recipe landed at docs/cookbook/rolling-console.md. Walks the buffer + scrollOffset + autoTail pattern with key routing, mouse-wheel scrollback, and bounded history; ChatStreamApp is the worked example. Native terminal scrollback explicitly stays a post-1.0 §5.3 idea, not the default contract.
  • 2026-04-30 — Stage 4 §4.9 closed: reduced-motion flag landed. TERMFLOW_REDUCED_MOTION env var (and HOCON termflow.accessibility.reduced-motion) flows through RuntimeCtx.config.accessibility.reducedMotion; Spinner accepts reducedMotion: Boolean and pins to frames(0) when true. New docs/guide/accessibility.md page covers the colour, motion, and predictable-structure stance.
  • 2026-04-30 — Stage 4 §4.10 closed: thread-model documentation landed at docs/reference/thread-model.md. Diagrams the topology (runtime thread, InputKey producer, Sub.Every scheduler, FCmd executor, resize listener, shutdown hook) and the invariants apps can rely on (`update` / `view` always on the runtime thread, FCmd continuations come back via the bus, subs lazy-start, CmdBus serialises, etc.).
  • 2026-04-30 — Issue triage: 25 completed issues closed; #154 (relative-coordinate VDom), #119 (Layout v1→v2 migration guide), #116 (horizontal scroll), and #117 (partial left-edge clip) all closed as superseded — the first two because the current Layout DSL already supplies the relative-coordinate tree and there are no v1 users; the latter two because Layout.Scroll / Layout.Clip only ever existed on the abandoned feature/layout-cookbook branch and never shipped publicly. Two new entries added to §4 as 1.0 scope: §4.9 (reduced-motion flag — #139) and §4.10 (thread-model documentation — #134). #141 (TuiRuntime error-path tests) scoped down to two remaining gaps (Sub mid-stream exception, CmdBus overflow); not a 1.0 blocker.
  • 2026-04-30 — Stage 4 §4.7 closed: coverage-uplift branch merged (a971a94). termflow-terminal 66% → 88% stmts / 63% → 90% branches, termflow-screen 72% → 91% stmts / 65% → 77% branches, termflow-app 80% → 87% stmts / 69% → 81% branches. All four published modules now ≥87% statement coverage; the priority targets (-terminal, -screen) are both above 87%.
  • 2026-04-30 — Stage 4 §4.8 closed: ciCheck is warning-free and unidoc clean of unresolved-link warnings. Five Scaladoc [[…]] references rewritten to qualified forms; a non-exhaustive Keymap.renderKey match closed by adding the InputKey.NoOp arm. The remaining Flag -classpath set repeatedly is a structural sbt-unidoc / Scala-3-doctool warning with no in-tree fix.
  • 2026-04-30 — Stage 4 §4.3 closed: public-API and docs-example audit swept eight signature drifts out of the tutorials, guides, and cookbook; docs/reference/migration.md populated with the explicit "no migration required for 0.2.x → 1.0" statement plus a catalogue of additive changes. mdbook build (with linkcheck) clean.
  • 2026-04-30 — Killer demo (§3.3) will live in llm4s, not in this repo. Reason: llm4s already depends on termflow for samples, so hosting an llm4s-backed demo here would create a sibling cycle even if the published-artifact graph stays acyclic. Termflow's README will link to the demo and show its screenshot.
  • 2026-04-30 — Stage 4 §4.1 closed: SimpleANSIRenderer now overlays a red, bold banner for Cmd.TermFlowErrorCmd and clears it on the next frame; testkit captures the same path via observedErrors.
  • 2026-04-30 — Stage 4 §4.4 closed: Layout.toBudgetedRootNode is the deferred sibling to the eager toRootNode; new full-screen-layout cookbook recipe explains when each form is appropriate.
  • 2026-04-30 — Stage 4 §4.6 closed: LogView.scrollDelta + LogView.Viewport give apps a one-call hook for mouse-wheel scrollback; wired into chatDemo and covered with MouseSim.
  • 2026-04-30 — Terminal-attention notifications shipped: Cmd.RequestAttention and Cmd.Notify(title, body) with detection for iTerm2 (OSC 9 / 1337), kitty (OSC 99), VTE (OSC 777), and a BEL fallback. Override via TERMFLOW_NOTIFICATIONS=off|bell|auto. Wired through the showcase Help tab and a new notifications cookbook recipe.
  • 2026-04-30 — Added rolling console renderer (§5.3) as a post-1.0 idea: native terminal scrollback for agent / command-runner UIs via a constrained normal-buffer runtime, not the default full-screen renderer.
  • 2026-04-30 — Added Stage 5 (§4) as the pre-1.0 release-hardening checklist: user-visible errors, release-doc accuracy, API/docs audit, layout ergonomics, rolling-console UX, mouse-wheel scrollback, coverage quick wins, and zero-warning builds.
  • 2026-04-30 — MiMa (§3.1) deferred to post-1.0; baseline becomes 1.0.0. Reason: 0.2.0 is already API-stable, so the 0.2.0 → 1.0 filter list would be mostly noise, and decoupling §3.1 from §3.5 removes a chicken-and-egg dependency.
  • 2026-04-30 — Stage 4 §3.2 closed: tree/ (#188), editor/ (#189), and streaming chat/ (#190) sample apps landed. Catalogue at 22.
  • 2026-04-30 — Stage 4 §3.4 closed: Layout.Grid + Layout.Border shipped in #187 with LayoutGridSpec / LayoutBorderSpec coverage.
  • 2026-04-29 — Docs site launched (Stage 4 §3 complete except for migration guide). mdBook + sbt-unidoc on GitHub Pages.
  • 2026-04-28 — Stage 3 final components landed: actionList dialog, ScrollBar, Separator, SplitPane drag-resize, hit-test cache (HitTest[Id] + Layout.Zone + resolveTracked), grapheme-aware navigation, MultiLineInput.
  • 2026-04-28Cmd.FCmd decision: stay on scala.concurrent.Future
    • Result[A]; no cats-effect / zio modules planned. Apps bridge to Future at the Cmd boundary.
  • 2026-04-27 — Stages 1 and 2 closed. Module split shipped early as Stage 4 prep so MiMa filters can be wired per-module on day one.
  • 2026-04-26 — Decision to deprioritise Swing/AWT and SSH backends (now §5.4); Telnet (§5.1) and Web (§5.2) remain.