Skip to content

Releases: steven-pribilinskiy/polygit

v3.24.1

Choose a tag to compare

@github-actions github-actions released this 27 Aug 20:11
fix: empty diffs stay put

v3.24.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 23:36
feat: the file explorer stops forgetting where you put it

Its floating window kept a rect and clamped that rect back into the terminal on every
render, so moving it never stuck: the geometry was session-only and every open reseeded it
to 70%-centered. Position and size persist now.

Which is only safe because the model changed underneath it. Clamp-and-write-back destroys
a position the first time the terminal shrinks — the clamp overwrites the stored value, and
growing the terminal again leaves the window where the small one forced it. That was
survivable while the geometry lived and died with a single open; persisting it would have
turned a transient annoyance into permanent loss. The window is now a corner plus an inset
plus a size, resolved fresh each frame by `tuilith::float`, which clamps for the frame it
draws and writes nothing back.

It also retires a latent panic. `resize_floating_to` and `resize_floating_step` computed
`bounds.x + bounds.width - floating_rect.x` on u16, which underflows for an origin outside
the viewport — safe only while `clamp_floating` was guaranteed to have run first, an
ordering convention between two functions in different files. There is no longer an origin
that can be outside the viewport, because the only way to obtain one is to resolve it
against the viewport it will be drawn in. That is the whole reason `float` went to tuilith
rather than staying here, and porting the explorer is what makes the claim real rather than
theoretical: two surfaces, one implementation, no convention to remember.

Six duplicated geometry methods became calls into the shared component, and the four
Alt+arrow arms collapsed into one delta lookup.

Three tests carry it: the position survives a shrink and a re-grow, re-opening restores the
geometry instead of reseeding, and resize/move are driven to their extremes against a 1x1
viewport without panicking. The tuilith side additionally implements the old
clamp-and-store model inline and requires it to FAIL the first of those, so the pair
distinguishes the designs rather than asserting the difference.

v3.23.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 20:26
feat: every metric in the perf panel explains itself

The labels are abbreviations forced by a 23-cell box — `flush`, `backlog`, `dropped`,
`overlay` — so the numbers were legible only to whoever wrote them. Dwell on a row and a
popover names the channel, says what it measures, and says what a bad reading indicts:
that flush is your emulator rather than this app, that a non-zero backlog is the
coalescing working and not a fault, that a frame rate idling at exactly 20 is a floor
imposed by the 50 ms poll and not a health signal.

Channel rows carry p50/p95/p99, worst-in-window, all-time peak and sample count. The rate
rows do not — a metric with no percentiles would need a line of zeros invented for it, and
a line of zeros reads as a measurement.

The popovers open away from the panel and are refused permission to flip. The panel draws
last so its own cost stays out of the channels it reports, which means anything overlapping
it is painted over; the side comes from which half of the screen the panel occupies, and
flipping is the one thing that could throw a popover back across it. `HoverTip` grew a
`flip` flag rather than the renderer special-casing an area, so the reason travels with the
tip.

Reuses the existing dwell machinery rather than building a second one: a `TooltipArea::Perf`
variant and one match arm, gated on the master tooltip switch like `Info` and with no toggle
of its own — the panel is already opt-in behind Ctrl+T, and a second switch would gate a
thing you had to ask for twice.

Verified by test rather than by eye, and the distinction matters: a unit test asserts every
metric row registers a region inside the panel, on the row it describes, with its prose and
its percentiles. The pty harness could NOT confirm the popover on screen — but a column
header's tooltip, which predates this change, does not appear in that harness either, so
the limitation is driving a one-second dwell through a pty and not a regression here.

v3.22.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 20:16
feat: the perf panel moves, remembers where you put it, and plots its…

v3.21.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 19:41
feat(coverage): build the selector in the panel, and preview where it…

v3.20.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 18:58
feat(coverage): the panel clones through the same engine as the command

The panel still had its own sequential clone loop while `polygit clone` used
the bounded one, so the two could drift on concurrency, skip reasons and
destination — three things it is not obvious have drifted until a clone
behaves differently depending on which surface started it. They are now one
engine, and git::clone_repo, which nothing else called, is gone rather than
left as a second way to do it.

The panel also discovers the new clones into the repo list when the run
finishes. Until now it only recomputed coverage, so a repo you had just cloned
was invisible in the list it was cloned into until a restart.

Ships as v3.20.0.

v3.19.1

Choose a tag to compare

@github-actions github-actions released this 22 Aug 17:48
fix: the perf overlay was charging its own weight to your terminal

Three defects in the instrumentation itself, found while extending it. Each made the
panel report something untrue, which is the only kind of bug a measuring tool cannot
have — and every one of them was invisible from the outside, because a wrong number
looks exactly like a right one.

- The overlay's own render cost was billed to `flush`. It was excluded from `build` by
  being drawn after it, and the comment said "excluded from every channel above" — but
  the event loop computed `flush = whole_draw - build`, and `whole_draw` wraps the
  overlay. So the panel inflated the exact channel `verdict()` reads to conclude
  "TERMINAL FLUSH - the emulator is the slow part". It now times itself into an
  `overlay` row and a pure `attribute_frame` subtracts it. Measured with the panel open:
  0.09 ms p95, which was going to the emulator's account.

  The residual limit is in the code and stands: the extra cells the panel puts in
  ratatui's diff ARE real work for the emulator. This removes our layout cost, not the
  emulator's cost of drawing us, so a panel-open `flush` is still slightly pessimistic.

- `motion/s` and `event/s` were always the same number. Both counters were incremented
  on adjacent lines inside `if kind == Moved`, so no key, click, wheel, drag or resize
  was ever counted, and `backlog` described only motion coalescing rather than queue
  depth as its own doc claimed. Two rows on screen showing one fact. Every event now
  counts, carried to the next frame so the hot path takes no extra lock. Verified
  through a pty: six keypresses plus a quit now show as 4330 events against 4323
  motions, where before the two totals were identical by construction.

- The `[x]`'s hover highlight was dead. `apply_hover` set the style and the overlay then
  drew `Clear` over the same cells, which resets them - computed, then wiped. This is
  the "clickable but dead on hover" miss CLAUDE.md names by name, in the code that
  quotes the rule. The panel paints its own hover now, which also means the highlight
  cannot lag a frame behind a panel that has moved. The regression test asserts the
  background actually changes, and fails on the old implementation.

Also: the panel is now opaque to the mouse. Only its `[x]` was hit-tested, so a click in
the middle of it selected the repo row behind it and a drag near its edge grabbed the
splitter underneath. Its whole rect is registered, like every other captured geometry.

And the `build`/`palette`/`hover` docs now say those NEST rather than sum — `build`
contains the other two, so a reader adding them up got a number that means nothing.

v3.19.0

Choose a tag to compare

@github-actions github-actions released this 20 Aug 18:32
feat: scrollbars get a column of their own, from a component that can…

v3.18.1

Choose a tag to compare

@github-actions github-actions released this 20 Aug 17:17
fix: icon glyphs keep their ink on their own background

A copy button beside dim text came out half in its own hover highlight
and half on the panel behind it. Thirteen glyphs do this, and the cause
is not width — they advance one column and `unicode-width` is right
about that, and so is a cursor-position report. No terminal monospace
font covers them, so the fallback draws them 1.16 to 1.71 cells wide and
the ink lands on the next cell, which belongs to the next span and
carries whatever style that span brought.

Every span that ends on one now carries the cell its ink lands on, and
every click region, hover rect, dwell tooltip and column budget around an
icon asks `icon_cols` rather than `UnicodeWidthStr::width`. The pad is a
space inside the same span, never a wider measurement: claiming two
columns for a one-column glyph would put every later region on the row a
column right of where it is drawn, which is worse than what it fixes.

The favourites column is two cells now. `★`/`☆` ink 1.42, and
`pad_display` could not supply the overflow cell at a budget of 1 — the
glyph already filled it, so the function returned early and the ink went
onto the kebab gutter beside it.

`🗖` and `🗗` were never two cells. They are single codepoints, which is
what the icon-set rule tests, but their East_Asian_Width is N, so
`unicode-width` reports 1. The comment beside them claimed 2 and said the
button renderer "measures display width, so the 2-cell glyphs lay out
correctly" — it does measure, which is exactly why the wrong number
mattered. `🏷` is the same. `📋`, `🔗` and `❌` are EAW=W, genuinely two,
and were always fine.

The confirm modal had its pad on the wrong side: `" ⧉"` puts a space
before a glyph whose ink spills after it.

The `IconSet` comments are corrected with the code. The header justified
the set by Geometric Shapes coverage, but `↯ ✗ ⚠ ★ ☆ ⧉ ↗ ✕` are Arrows,
Dingbats and Misc Symbols — the rationale never covered the glyphs that
overflow.

Measured against Cascadia Mono and the Segoe UI Symbol it falls back to,
by the screening script in the shefrd tree, and confirmed in a running
instance: the Path row's escape stream now carries `⧉ ` inside one
magenta run where the pad cell used to belong to the next.

v3.18.0

Choose a tag to compare

@github-actions github-actions released this 20 Aug 09:17
feat: Ctrl+T perf overlay + --perf report to find out why the UI feel…