Files
pebrel/scripts/launch_probe_instance.ps1
T
kuddev b795ebbc85 feat: live carets, one-chip keycaps, aligned path column, enforced UI contract
The visual work and the reason the visual work kept regressing, in one pass.

Picker and palette
- Rows drop their card borders: a row is transparent until hover/selection.
  Five ringed white rectangles in a column read as a form, not a list, and
  the panel-to-row lightness difference already separates them.
- Option paths start at one shared column instead of being right-aligned.
  Right alignment floated every row's path START with its own length
  (cmd.exe began ~300px right of Nushell's), so scanning meant hunting
  left and right per line.
- Footer hints drop their chips. A chip background means "clickable" here;
  the arrow/Enter/Esc legends aren't buttons, so key and description
  separate by ink weight instead.

Keycaps go back to one chip per combination
Per-key chips are a macOS form, where the modifiers are single-character
glyphs that tile evenly. Ctrl/Shift/Alt are words, so splitting produced a
row of ragged blocks; and Windows users already read Ctrl+Shift+P as one
string in VS Code and Office.

Carets that look alive
The blink phase hung off the wall clock, so a field taking focus had a 50%
chance of showing its caret up to half a second late — which reads as "not
focused". Phase now starts at the last edit: lit immediately, steady while
typing, breathing only after the hand stops, at the system's
GetCaretBlinkTime (including the accessibility setting that disables
blinking). The palette was also missing from the fast-redraw list, so its
caret froze once the open animation ended. The palette caret is now a
1.5px beam rather than a full-cell glyph, which lets placeholder and real
input share one x — the first keystroke no longer shifts the line.

Overlays share one recipe
Confirm dialogs and the SSH editor gain a real drop shadow and the common
radius; both previously drew hairline + fill only, so a dialog demanding an
answer floated lower than the palette you dismiss with Esc. The SSH
editor's dim was a hard-coded 67% black ignoring the theme. Dropdowns cast
a shadow instead of a glow (a glow spreads brightness without establishing
height) and are opaque, since a menu sits directly on the content it hides.

Why this kept regressing
ui/mod.rs has said "layer contract: no magic numbers" for a while, and
widgets.rs violated it — a constraint expressed only in a comment is not a
constraint. ui/guardrails.rs turns three of them into failing tests, each
carrying a budget equal to today's real count: new violations fail the
build, and clearing old ones fails it too until the budget is lowered, so
the number only goes down. This pass: radius 121 -> 94, strokes 69 -> 56,
glow-as-shadow 12 -> 9.

Probe script now runs a COPY of the debug binary. Running the build output
directly makes the next cargo build die with an opaque mingw link error,
and it invites cleaning up by image name — which would kill the user's own
window, possibly the one hosting this session.
2026-07-29 20:39:37 +08:00

50 lines
2.0 KiB
PowerShell

# Launch a debug nebula instance for ui_probe and print its PID.
#
# It runs a COPY, never target/debug/nebula.exe itself. Two reasons, both hit:
#
# 1. Windows will not let a running exe be overwritten. Probing the build
# output directly makes the next `cargo build` die with
# "linking with x86_64-w64-mingw32-gcc failed", while the real cause
# (file in use) is buried under a wall of mingw .drectve warnings.
#
# 2. The probe instance must be disposable, and the user's own Nebula window
# must never be collateral. Different exe paths remove any temptation to
# clean up by image name. NEVER run `taskkill /IM nebula.exe` here: the
# active Claude Code session may itself be hosted in a Nebula window.
#
# conpty.dll and OpenConsole.exe are copied alongside: the Windows PTY backend
# looks for them next to the exe, and the instance cannot open a shell without
# them.
param(
[string]$SourceDir = "D:\temp_build\nebula\target\debug",
[string]$ProbeDir = "D:\temp_build\nebula\.probe",
[string]$WorkingDir = "D:\temp_build",
[int]$WarmupSeconds = 7
)
$ErrorActionPreference = "Stop"
New-Item -ItemType Directory -Force -Path $ProbeDir | Out-Null
foreach ($name in @("nebula.exe", "conpty.dll", "OpenConsole.exe")) {
$src = Join-Path $SourceDir $name
if (-not (Test-Path $src)) {
Write-Error "missing build artifact: $src (run cargo build -p nebula --bin nebula first)"
}
# A previous probe may still hold the same file. A failed copy means it is
# alive; say so, and point at killing it BY PID rather than by image name.
try {
Copy-Item $src (Join-Path $ProbeDir $name) -Force
} catch {
Write-Error "cannot overwrite $name - a previous probe instance is probably still running. Close it with ui_probe.ps1 -ProcId <pid> -Kill."
}
}
$exe = Join-Path $ProbeDir "nebula.exe"
$p = Start-Process $exe -ArgumentList '--working-directory', $WorkingDir -PassThru
Start-Sleep -Seconds $WarmupSeconds
$p.Refresh()
Write-Output ("pid=" + $p.Id)
Write-Output ("exe=" + $exe)