Found by driving a dev instance and measuring what an idle window costs.
Two of them were frame loops that never stopped. A `Head` diff overlay
calls itself stale when the cached git status disagrees with the snapshot
on screen, and every landed probe wakes that check by touching the cache
— but the read published its counts and left the branch behind, so a
branch switched outside tty7 made the disagreement permanent: two `git`
processes a lap, forever, with `refreshing…` pinned to the header and an
idle window at 7% of a core. And the home page asked for a frame sixty
times a second to change one glyph's opacity twice, which made a window
with nothing open in it eight times more expensive than one running a
shell. Both now settle: the diff read publishes the branch it found, and
the home cursor flips a bool on a timer the way the terminal's own does.
The rest:
- The tab sidebar and the right panel each capped themselves at half the
window and knew nothing about the other, so together they could take
all of it — 260 points of terminal on a 720-point window. Both now cap
at whichever binds harder: half the window, or what is left after the
terminal's floor and the other panel's floor. The same cap bounds the
drag, so a panel dragged to its limit stays where it was dropped.
- Only a HEAD diff may correct the sidebar's counts. Those numbers mean
`git diff --numstat HEAD`; an unstaged or staged patch answers a
smaller question, so opening an untracked file from the Source Control
panel took the staged lines off the total on the click.
- An untracked row in the diff overlay had no click target, and once
focused could not be left — the breadcrumb looks the path up in
`files`, where an untracked file has no entry. Both ends fixed.
- A new pane keeps the name its directory was reached by. `cwd()` alone
loses it: the shell falls back to `getcwd()`, so `/tmp/x` became
`/private/tmp/x` in every tab opened from the first. `PWD` carries it,
and POSIX has the shell discard a `PWD` that names the wrong
directory, so this can correct the name and cannot invent one.
- The settings search now sees into the Keybindings page, which is
generated from the binding table rather than the static index — so
searching for a feature finds its shortcut, and the page filters to
the matches. Closes#444.
- The settings reading column is centred rather than pinned to the nav:
on a window as wide as the display it was made for, 640 points of
settings sat beside 1600 points of nothing.
- `New Workspace…` takes the ellipsis its three sibling actions already
carry — it opens a form asking for a name and a host.
Every fix has a test. The re-probe loop is pinned end-to-end with
`render_probe::draws() == 0` against a real repository, confirmed to
fail on the old behaviour before it was kept.
38 pages under docs/, written against the source rather than the README:
config keys and their clamps from core::config, default keybindings from
ui::keymap, every CLI verb and flag from tty7-cli, agent aliases and
hook/fork/resume support from core::cli_agent, and Settings paths taken
from the actual en-US strings.
docs/features.md and its zh-CN translation are retired — everything in
them now lives in a page of its own, plus the two things they carried
that nothing else did (IME input, the performance notes). README and
README.zh-CN point at docs/ instead.
Screenshots and videos are placeholders for now: docs/images/placeholder.svg
with a caption naming what each shot should be.
Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>