Conversation
A terminal renders on a character grid, so a window whose pixel width or height is not a whole multiple of the cell size keeps the remainder as an unpainted strip along its right and bottom edges. The chrome cannot reach it: SGR and back_color_erase address cells, so neither the per-line ESC[K nor the trailing ESC[0J touches that strip, and the terminal fills it from its own default background instead. Against a themed canvas the seam is plainly visible, and worst when the window is maximized or snapped, where snapping the window to the character grid is not an option. OSC 11 moves the terminal's default background to the theme's base00, which is the only lever an application has here. Windows Terminal declined to paint the gutter from the adjacent cells (microsoft/terminal#19860, closed as not-planned), so this is not a stopgap awaiting an upstream fix. Three properties are load-bearing. The guard derives from Get-WatchChrome rather than restating its conditions, because the gutter and the canvas have to agree in every case and one predicate is the only way to guarantee that. The OSC 111 reset is conditional on the entry having emitted an OSC 11: under the default theme sca never moves the background, so resetting anyway would discard one the user set on their own terminal before launching. And the reset is written before ESC[?1049l, where it shows for one frame in the gutter alone; after the alt-buffer leave it would instead flash the theme background across the restored scrollback.
The alternate screen has no prompt or margin of its own, so the frame sat flush against the window on every side. Two columns and one row lift it off, which is enough to read as a deliberate canvas and small enough that the table still fits the 80-column terminal its column widths are measured against. Only the top and left are written: the right edge is already reached by each line's ESC[K and the bottom by the trailing ESC[0J, both of which fill with chrome. The inset cannot be a pure post-transform. Write-UsageTableHeader and the aggregate-bar clamp right-align against the terminal width and reserve a single column, so indenting a frame laid out against the raw width would push the -Auto indicator two columns past the right edge and wrap it. Get-RenderWidth answers what a renderer may lay out in, leaving Get-ConsoleWidth honest about the terminal; both existing call sites move over, and an unknown width (0) still propagates unchanged. The value is ambient rather than a parameter because its two consumers sit at opposite ends of the render: the transform, which applies it, and layout code several frames deep inside the renderer. Threading it would put a presentation argument on Format-UsageFrame, Format-UsageTable and Write-UsageTableHeader, all three of which are also reached from non-watch callers that would have to pass 0. Write-WatchFrame owns the window, raising the pair for one paint and dropping it in a finally, so every scrollback renderer still sees 0 and `sca list` / `sca save` / one-shot `sca usage` stay flush left, where an indent would be noise and would break copy-paste.
The italic line under a version heading is Common Changelog's notice (2.3), and three releases opened theirs with "Upgrading is replacing one file". That is not a property of any release: it is what upgrading always is for a single-file tool, and README.md -> Download plus the zero-dependencies bullet already say so. Repeating it spent the one position a reader looks at first on a constant, and pushed each notice to two sentences where 2.3 asks for one. Removing it leaves 4.1.0 and 4.0.0 stating only their real prerequisite, both now a single sentence. For 4.2.0 nothing was left: the remainder restated the three Changed entries directly beneath it, which the categories already sort by impact, so the notice goes entirely. The four notices that lead with a genuine delta are untouched. conventions.md carried the rule that permits the line but not the two limits that were being broken, so it now names 2.3, says one sentence, and says what stays out: the baseline install mechanics, and a summary of the entries below it. A reader who skips a notice must lose nothing.
Minor rather than patch: the gutter fix is a bug fix, but the frame inset changes where existing output lands on screen, and a named SCA_THEME now reaches the terminal's own background color, which is state outside the alternate screen buffer and outlives a hard kill. The notice names only the background, not the inset. The inset is cosmetic and its Changed entry carries it; the background is the one thing in this release a reader would otherwise meet by surprise.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two changes to how the watch frame sits in the terminal window, plus a changelog cleanup.
sca monitorandsca usage -Watchleft a dark strip along the window's right and bottom edges under a namedSCA_THEME: the pixel remainder ofwindow_size % cell_size, which the terminal paints from its own default background and which per-cell SGR cannot reach at all. The same frame also sat flush against the window on every side, the alternate screen having no prompt or margin of its own to lift it off.Upgrading is otherwise replacing the one file, with one thing worth knowing: under a named
SCA_THEMEthe watch now sets the terminal's own background color with OSC 11 and resets it with OSC 111 on exit. That is state outside the alternate screen buffer. Thedefaulttheme and-NoColor/NO_COLORnever touch it.4.3.0
base00for the duration of a watch, so the unreachable pixel gutter matches the canvas instead of seaming against it.Get-RenderWidth, splitting "what may I lay out in" fromGet-ConsoleWidth's "how wide is the terminal", so right-aligned content stays inside the inset instead of wrapping.docs/conventions.mdthe two Common Changelog §2.3 limits it was breaking.Not breaking. Minor rather than patch because the inset moves where existing output lands and the OSC 11 reaches state the tool has never touched before.
Why OSC 11 at all
Terminals render on a character grid and a window is rarely a whole number of cells.
ESC[KandESC[0Jfill with the current background but address cells, so the remainder strip is unreachable by construction, no matter how the frame is painted. Moving the terminal's default is the only lever an application has. Windows Terminal declined to paint the gutter from the adjacent cells (microsoft/terminal#19860, closed as not-planned), so this is not a stopgap waiting on an upstream fix.Shortcomings
Exit-WatchTerminalrestores it in afinally, which covers Ctrl-C and a throw, but ataskkillor a closed pty leaves the tab tinted until it is closed. The alt buffer has always had the same exposure; a tinted tab is arguably the less obvious of the two to recover from.$Script:FramePadColumns/FramePadRowsare ambient.Write-WatchFrameis the sole owner and the sole frame painter, so this is currently sound, but a future renderer that paints a frame without going through it would silently get 0 rather than fail.Get-WatchBackgroundOscis unreachable while the suite pinsBackgroundRgbtoBackground. It is kept because without it a hand-written palette missingBackgroundRgbwould emitrgb:00/00/00and tint the terminal black rather than do nothing. It shows up in the coverage residue.Feedback wanted
ESC[?1049l, on the reasoning that the alt screen's cells all carry chrome so the reset shows for one frame in the gutter alone, whereas after the leave it would flash the theme background across the restored scrollback. That is reasoned, not measured.Format-UsageFrame→Format-UsageTable→Write-UsageTableHeader, all of which also serve non-watch callers that would pass 0. I think ambient is right here and would like it challenged.What is not done
sca monitor. Every action here writes the real~/.claude, so the suite proves the byte sequences and nothing proves the strips are actually gone on screen. That check is yours to make. If they persist, the remaining suspect is the Windows Terminalpaddingprofile setting rather than the sub-cell gutter, which is asettings.jsonfix and not a code one.tests/Invoke-WatchPtyProbe.ps1was not extended. It would be the one real end-to-end proof, but it runs themeless, so an OSC 11 marker would simply MISS; proving anything needsSCA_THEMEplumbed into the probe's inner run first.docs/images/was not re-rendered. The README scenes are hand-authored literals intools/Render-ReadmeImages.ps1, not captures, and freeze already draws its own canvas margin, so adding the inset there would read as double padding.