master #17

Closed
clawdie wants to merge 0 commits from master into master
Owner
No description provided.
refs #3883

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #3895
refs #3900
refs #3922

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #3949
refs #3785
refs #2396
Codex's Windows input reader does not surface bracketed paste. It buffers
the prompt as a paste burst and rewrites a following Enter into a newline
until the burst idles out, so the previous size-based delay only reduced
the chance of losing the submit. Append a non-character key after the
paste so Codex flushes the burst synchronously, giving every prompt a
deterministic submit boundary.

refs #3187
Native Windows lint and check only clippy-checked the herdr binary, while macOS and Linux run clippy across all targets. Enable --all-targets on Windows and gate the Unix-only test helpers that this exposed so Windows check matches the Unix one.
* fix(config): keep utf8 bom from breaking config reads and writes

refs #3678

* fix(config): only strip displaced boms when config is invalid

refs #3678

* fix(config): strip only boms the toml parser rejects

refs #3678
* fix(remote): show SSH authentication output

refs #3606

* test(remote): stabilize SSH authentication output regression

refs #3606

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* ci: retain zig build caches across validation runs

* ci: reduce debug information in validation builds

* ci: build only the ghostty test target for scalar checks

* ci: measure debug profiles and remove duplicate macos caching

* ci: compare scalar build scopes on one runner

* ci: keep the zig compiler path stable across runs

* ci: run macos and windows lint alongside tests

* ci: inspect remaining zig cache misses

* ci: remove completed measurement probes

* ci: compare windows linkers without changing release builds

* ci: test linux incremental reuse and correct the linker probe

* ci: measure windows incremental state reuse

* test: verify incremental reuse after a source change

* ci: finalize measured compiler cache optimizations
refs #1836
* fix: support opencode v2 lifecycle reporting

* fix: repair Japanese docs

* fix: ignore payload-less OpenCode events

* fix: harden opencode v2 integration install and reporting

Follow-ups on top of the V2 lifecycle support:

- create `cli.json` when OpenCode has no V1 TUI preferences (`tui.json` or
  `kv.json`) to migrate, instead of only registering into an existing file
- settle stalled socket attempts with a plain connect timer, and resend the
  latest lifecycle state after a failed delivery so the pane cannot get stuck
- resolve the OpenCode state directory from `XDG_STATE_HOME`
- remove the managed `herdr-opencode` directory on uninstall
- document failed executions reporting `blocked`, keep the integration test
  environment independent of an inherited `XDG_STATE_HOME`, and simplify
  `reconcileBlockers` to reassign its map

---------

Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com>
refs #3948

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #2593
refs #3651
refs #3651
refs #3833

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #3314

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #3988
* fix: honor space row gaps across machines

refs #3738

* test: cover scrolling with machine space gaps

refs #3738

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #3329
* fix: update grok session after new

refs #2681

* fix: avoid powershell args shadowing

refs #2681

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
The polling peer drains at production's 2ms Windows read cadence, so a 1 MiB
frame took ~5.5s locally and exceeded the test's 10s flush deadline under CI
load. Use a 256 KiB frame, still well above the 64 KiB batch limit, and a 30s
deadline so the assertion no longer depends on CI scheduling.
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: order ui accent before nested config tables

refs #2697

* test: reject duplicate ui accent examples

refs #2697

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #3295

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #4018

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #3710

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Windows CI runs these documentation contract fixtures under variable load. A degraded runner pushed the preview and versions snapshot integration tests past their 30s ceiling, while a healthy run finishes in seconds. Keep 30s elsewhere and give Windows a 120s ceiling.
refs #3911

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Live handoff refused any session with more than 64 panes. The pane count
was checked twice against MAX_FDS_PER_HANDOFF, and the transfer itself put
every pane's pty master into one SCM_RIGHTS control message, so the guard
was the only thing keeping the send inside the kernel's per-message limit.
A session past the limit could only be updated by closing panes or by a
normal restart, which ends every pane process.

Send the descriptors in batches of 64 instead and drop both guards. The
receiving side accumulates across recvmsg calls until the expected count
arrives, bounds every SCM_RIGHTS payload it reads by the control bytes the
kernel returned, rejects a batch that carries more descriptors than it
asked for, and closes the descriptors it already holds on any failure. A
session of 64 panes or fewer still produces one batch, so the bytes on the
wire are unchanged and HANDOFF_VERSION stays at 1.

refs #3393

Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
The clear-only metadata test used a 1 ms ttl, so on loaded Windows runners set_agent_metadata could see the entry as expired, drop it, and recreate it with a None ttl before next_agent_metadata_expiry() ran. Expiry is forced explicitly later in the test, so use a long ttl to keep the no-extension assertion independent of wall-clock scheduling.
refs #3317
Windows OpenSSH resolves drive-letter Include paths, but Git for Windows' MSYS OpenSSH does not, so the managed remote SSH config silently ignored the user's ~/.ssh/config when herdr ran under Git Bash. Include the user config through ~/.ssh/config, which both implementations expand to the same file.

refs #3947
refs #3106

Co-authored-by: Cameron <cameron@pfiffer.org>
Windows skipped the xterm mouse-reporting reset because clear_host_mouse_reporting was a no-op there. Standalone Git Bash (mintty) keeps SGR mouse reporting enabled after detach, so mouse motion leaks escape sequences into the shell. Emit the reset sequence on Windows too and include the X10 mode.

refs #3748
* fix: keep hermes enabled list valid yaml

refs #3839

* fix: preserve hermes inline list quoting and comments

refs #3839
refs #2692
* fix(windows): honor default_shell in login shell mode

Login-mode panes used portable-pty's default-program builder, which resolves to %ComSpec% (cmd.exe) on Windows and ignores the SHELL env override, so [terminal].default_shell was silently ignored. Build the launch command from the configured shell instead and append the shell's own login flag for POSIX-style shells that support one.

refs #1445

* fix(windows): add csh and tcsh to login shell flags

refs #1445
Windows login-mode PowerShell panes are now launched directly, but the PowerShell prompt-based cwd integration was still gated to non-login mode, leaving those panes without repository-owned cwd reporting after Set-Location. Enable the existing integration for login-mode PowerShell and build the integration args on the shared direct-shell path.

Follow-up to #4060.
A process-exit observation is not proof the agent is gone: the same
observation can be wrong while the agent keeps running, and the name is
the only handle its owner has on the pane. Detection uncertainty already
preserves the name, so releasing it on the observation alone contradicts
that contract and leaves a live agent unreachable by name with a rename
as the only recovery.

Free the name at the point the agent actually leaves the pane - a
recorded exit with no agent detected any more - so a wrong observation
costs nothing and a real exit still releases the name for reuse.

refs #3225

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: auto-expire worktree action error banners

refs #1827

* fix: restart endpoint error timeout on repeated errors

Route every transient client-side action error through a setter that installs a fresh deadline, so an identical repeated message cannot inherit an older, nearly-expired deadline.

refs #1827

* test: derive endpoint error expiry assertions from stored deadline

refs #1827
refs #3670
Codepoints 57364-57375 (F1-F12) were missing from the kitty-protocol codepoint table, so terminals that send function keys as full CSI-u sequences (e.g. Ghostty, which enables the kitty keyboard protocol by default) had those keys silently dropped. Confirmed live against a running herdr session: injecting the raw F3/F4 codepoint sequences did nothing before this fix and correctly triggered previous_tab/next_tab after.

refs #1809

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Terminals such as foot send F1-F4 as parameterized CSI-tilde sequences (for
example F3 as `\x1b[13;1:1~`). `parse_xterm_modified_special_sequence` mapped
codes 15-24 but not 11-14, so these presses were dropped before keybindings
saw them. Map 11-14 to F1-F4, matching the unmodified `\x1b[11~`..`\x1b[14~`
aliases already accepted.

refs #1809
refs #3612
* feat: install windows remote host packages

refs #3651

* docs: clarify windows saved reconnect package behavior

refs #3651

* fix: include windows installer in nix sources

refs #3651

* fix: preserve paths in windows scp transfers

refs #3651

* refactor: isolate windows remote package setup

refs #3651
refs #1282
refs #3621

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* ci: migrate remaining pinned actions to node24

actions/cache@v4 and mlugg/setup-zig@v2.2.1 still target Node 20, which
GitHub removes from runners on 2026-09-23. Bump actions/cache to v6.1.0 and
replace mlugg/setup-zig with vercel-labs/setup-zig@v1.0.2.

vercel-labs/setup-zig takes only `version`, so the use-cache/cache-size-limit
tuning and Zig global-cache reuse are dropped. See the PR for alternatives.

* ci: restore zig caching for vercel setup-zig

vercel-labs/setup-zig has no cache controls, so redirect the Zig global cache
into the workspace .zig-cache and run the Zig build cache step on Linux too.

Drop this commit if we switch to a setup action that owns Zig caching, e.g.
step-security/setup-zig or xyzzylabs/setup-zig.
* fix: scope agent views to the selected machine

refs #3732

* fix: preserve stable agent view ordering

refs #3732

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Co-authored-by: dengos <dengoswei@gmail.com>
* test(windows): deflake media player invalid media assertion

The Windows sound test required MediaPlayer's MediaFailed event for invalid
media. Some runners never raise it, so the script exits through its playback
timer and the test saw "sound playback timed out" instead, panicking on the
MediaFailed assertion.

Accept either terminal error and keep the timer short under test via
HERDR_SOUND_TIMEOUT_SECONDS so a missed MediaFailed no longer waits out the
production 15 second bound.

* test(windows): keep media player timeout override test-only

Generate the short-timer player script only in tests instead of reading a
process environment override. This keeps the production script's fixed 15
second bound unchanged, and the script-content test now proves the test
variant rewrites the timer.
* fix: clean up idle ssh bridges and back off flapping connections

* chore: keep ssh liveness smoke tooling local
refs #3937

Root cause:
Activating another endpoint applies a snapshot with a different
endpoint-qualified graphics scope. This triggers reset_endpoint_projection,
which clears agent_scroll together with endpoint-local state even though
the agent list aggregates all machines. The selected agent receives focus,
but the list jumps back to the top.

Fix:
Save the client-owned agent scroll offset and restore it only when
activation changes endpoints. Keep same-endpoint reboot resets,
workspace/tab scroll resets, input cleanup and existing list bounds
clamping unchanged. This adds constant-time work on endpoint activation,
with no protocol, persisted-state or pane-scaled rendering changes.

Validation:
The new regression fails on the original implementation with scroll 0
instead of 6. Tests cover repeated bidirectional agent clicks, stable
visible rows, shrinking lists and same-machine reboots. All 242 client
shell tests pass.

Real SSH A/B testing against the same two disposable 0.9.0 servers
reproduces the reset with both the stable and current-master clients.
The patched client preserves the visible rows through six cross-machine
switches and two same-machine control clicks.

Native just ci passes: 3535 Rust tests, six default skips, plus lint,
maintenance, architecture and integration-asset checks. All seven docs
contract tests pass. Windows cross-lint was not run because its SDK is
not installed; native macOS and Windows UI behavior was not tested.
* fix: detect codex activity with static titles and queued inputs

refs #4092

Codex 0.154.0 can omit the activity bullet when tui.animations is false
and replace the literal Working label with a task-specific label. Its
terminal title can also remain static during an active turn, so the OSC
spinner rule is not sufficient to identify work.

The screen fallback required a bullet followed by Working in the last
three non-empty lines. It therefore missed both the animation-disabled
status line and dynamic labels. Queued follow-ups add a heading, input
text, and an edit hint below the activity line, moving that line outside
the three-line region. The lower-priority non-empty OSC title rule then
reported idle while Codex still showed an active timer and interrupt
control.

Recognize the elapsed-time and esc-to-interrupt controls in the detection
snapshot before the current composer. Allow an optional bullet, a dynamic
activity label, and queued follow-ups below that line. Require that no
later response, completion, or interruption marker supersedes the live
activity. This excludes composer text and stale output without letting an
earlier interruption suppress a subsequent active turn.

Keep OSC state precedence and transcript-viewer skip behavior unchanged.
Update the bundled and distributed manifests together to 2026.09.14.1.
Add regression coverage for optional bullets, dynamic labels, queued
inputs, resumed work after interruption, and stale or quoted controls.

Avoid discarding Regex search caches on every detection poll. The loader
previously cloned the entire compiled rule vector, and each Regex clone
created a fresh search cache pool despite sharing compiled read-only
state. Share the immutable rules through Arc instead. Reload publishes a
new array while in-flight readers retain a valid old generation, without
holding the global cache lock during matching. Add a cheap contains gate
for the required interrupt text before running the multiline expression.

Add a deterministic regression for compiled-rule sharing, reload
replacement, retained old readers, and concurrent detection. Measure the
baseline and optimized detector kernels in three alternating rounds on
CPU 24 with NUMA node 0 and CPU 25 with NUMA node 1. Real queued detection
falls from about 116 to 22 microseconds, and two evaluations per pane over
15 panes fall from about 3.45 to 0.65 milliseconds on both sockets, about
81 percent less time. No benchmark match results change. The cache
improvement requires the updated binary, not just a manifest reload.

Validate on the official Herdr 0.9.0 release with Codex 0.154.0 by toggling
the old and new manifests during the same active queued task. Confirm
working for active turns and idle after completion or interruption.
Pass 86 captured-screen and semantic checks through the optimized source
binary, 69 manifest/cache tests, CPU-pinned render scaling, and the full
native CI suite: 3535 Rust tests passed, with six default skips. Run CI
serially with inherited Herdr session context removed; no tests were
excluded or expectations relaxed to make CI pass.

* fix: detect codex pending follow-ups as working

refs #4092

* fix: handle wrapped codex follow-up hints

refs #4092

---------

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
refs #3629
refs #3842
refs #4091
refs #3932
refs #3702
refs #3910
* fix: keep modified enter compatible with legacy panes

refs #4103

* fix: synchronize modified key negotiation state

refs #4103

* test: cover windows legacy modified enter

refs #4103

---------

Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com>
* feat: add cursor-based editing to text inputs

refs #1803

* fix: preserve dialog actions with associated text

refs #1803

* refactor: simplify text editor outcomes and tests

refs #1803

---------

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

* fix: atomically write integration configs

refs #3970

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #3295
refs #3932
refs #3932
refs #4151

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #4153

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Root cause:
The handoff test starts an agent immediately after workspace creation,
before the new shell is necessarily ready. The reconnect test assumes a
fixed sidebar row and searches raw ANSI output for text that can arrive
as separate incremental cell updates.

Fix:
Wait for a shell builtin to write a readiness marker before sending the
single raw agent.start request. Exercise the gap with a delayed shell.
Locate the recovered workspace in the rendered sidebar and check the
reconstructed screen for selection and input, including overlay borders.
Do not extend existing timeouts or add retries that hide failures.

Validation:
All 25 affected group and helper tests pass. Ten repeated rounds of the
two runtime tests and the row helper pass, for 30 test executions without
retries. Standalone native just ci passes 3582 Rust tests with six default
skips, formatting, all-target Clippy, 106 maintenance tests, six architecture
tests and 39 integration-asset tests. Windows cross-lint was not run because
its SDK is not installed.

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #4153

Root cause:
A no-focus pane move can remove the source tab without changing the
server's numeric workspace and tab coordinates. PaneMove is not classified
as a topology change, so a client viewing that tab retains its deleted ID.
Its target lookup falls back to the server default and can follow a later,
unrelated focus change instead of staying in the source workspace.

Fix:
Include PaneMove in the existing client-location reconciliation path.
Extend the existing focus-guard test with a client on the removed tab and
verify that a later server-default change cannot move its view. Preserve
the other client's view and existing error, no-op and zoom assertions.

Validation:
The minimized regression fails five times on PR #4159's unchanged head and
passes five times with the one-line fix. All 19 pane-move tests, native
lint, maintenance, architecture and integration-asset checks pass.
Full native just ci on the publication branch, including the unchanged
prerequisites from #4159 and #4168, passes 3585 Rust tests with six default
skips plus lint, 106 maintenance, six architecture and 39 integration-asset
tests. All seven docs contract tests pass. Local Windows cross-lint was
not run because its SDK is unavailable.

No geometry policy, protocol or periodic rendering behavior is changed.
refs #3841

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #4155
The v0.8.2 Windows archive shipped an herdr.exe that imported
VCRUNTIME140.dll and the api-ms-win-crt-* Universal CRT, none of which the
archive provides. Static CRT linkage was restored for x86_64-pc-windows-msvc
in .cargo/config.toml, but nothing verified the packaged executable, so the
dependency could silently regress.

Parse the PE import and delay-import tables and reject herdr.exe when it
depends on the dynamic Microsoft C/C++ runtime, including release and debug
variants. Check the input while staging and re-check the staged executable
before archiving so a direct archive cannot bypass the guard.

refs #3129
refs #4125
refs #4100
refs #3769

refs #3745
refs #3903
refs #3903
* fix: require exact session names before deletion

refs #3819

* test: isolate session deletion regression tests

refs #3819

---------

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Root cause:
The API socket is bound before App evaluates session restore. Waiting only
for that socket lets the late-session test inject its file during startup,
so the server may load it normally instead of exercising late-file recovery.
The missing backup then fails an otherwise correct persistence assertion.

Fix:
Wait for a read-only workspace-list request to pass through App and assert
that the workspace list is still empty before injecting the session file.
Keep the existing autosave deadline and byte-for-byte backup assertion.
Add no sleeps, retries, longer timeouts or production changes.

Validation:
The original assertion fails with unchanged master. With the barrier, five
independent runs pass. Full native just ci passes 3624 Rust tests with six
default skips, formatting, all-target Clippy, 112 maintenance tests, six
architecture tests and 39 integration-asset tests. All seven docs contract
tests pass. Local Windows cross-lint was not run because its SDK is absent.

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #1797
refs #4240

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #4252
refs #4251
refs #4251
refs #4251
backup_preserves_legacy relied on a freshly created temp file already having a legacy DACL (D:(...)). Directories that grant inheritable ACEs produce D:AI(...) instead, so the fixture failed before exercising the backup path. Install the legacy DACL explicitly, preserving the existing ACEs while clearing the auto-inherit and protected control bits.
refs #4251
* fix(windows): prefer pwsh for the default pane shell

Windows panes launched Windows PowerShell 5.1 (powershell.exe) whenever [terminal] default_shell was unset, ignoring PowerShell 7 even when pwsh.exe resolved on PATH. Resolve the unset default against PATH and prefer pwsh.exe, falling back to the inbox powershell.exe. An explicit default_shell still wins.

* fix(windows): validate pwsh before using it as the default shell

portable-pty resolves the configured shell with Path::exists and passes that path to CreateProcessW, which does not fall through to later PATH entries. Selecting an invalid pwsh.exe would therefore break new panes instead of falling back. Only prefer a pwsh.exe that starts with the PE MZ magic, and return its path so the validated binary is the one launched.

* fix(windows): validate the full PE header before preferring pwsh

Checking only the DOS MZ signature still accepted truncated images, DLLs, and foreign-architecture binaries. Because portable-pty passes the resolved path straight to CreateProcessW without trying later PATH entries, validate the PE signature, the COFF header (machine, executable-image bit, not a DLL, section count), and the optional header before preferring pwsh.exe.

* fix(windows): accept native ARM64 pwsh and validate the section table

Herdr ships an x64 Windows build that also runs on Windows ARM64 under x64 emulation, so cfg!(target_arch) cannot tell whether a native ARM64 pwsh.exe is launchable. Accept every executable machine type Windows supports instead of rejecting ARM64 on the x86_64 build. Also bound-check the section table (40 bytes per declared section) after the optional header so a truncated table falls back instead of being selected.

* fix(windows): detect the native host machine for pwsh compatibility

Machine compatibility was derived from cfg!(target_arch), which reports the emulated x64 process on Windows ARM64, and then briefly accepted ARM64 on every host. Read the native machine with IsWow64Process2 in the platform layer instead: ARM64 Windows accepts ARM64/x64/x86 images, x64 accepts x64/x86, and x86 accepts only x86.
Windows refuses file symlinks with ERROR_PRIVILEGE_NOT_HELD (1314) unless
the test process is elevated or Developer Mode is enabled, which broke
non-admin local runs. Share a helper that reports the missing privilege so
the two symlink tests skip only the symlink-dependent assertions.
* test: add local windows input gauntlet

refs #4251

* test: add local windows input gauntlet

Harden elevation and channel identity checks, distinguish known host limitations, and surface incomplete cleanup.

refs #4251

* test(windows): harden input gauntlet execution

refs #4251

* test(windows): make input gauntlet self-contained

refs #4251

* test(windows): bound input gauntlet failure paths

refs #4251

* test(windows): extend input qualification gauntlet

refs #4251

* test(windows): complete input qualification matrix

refs #4251

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com>
* fix(windows): preserve mouse capture during refresh

refs #4284

* test(windows): fix default input gauntlet invocation

* fix(windows): preserve pixel mouse transitions

refs #4284
refs #4333
* test(windows): qualify remote clipboard image paste

refs #4314

* test(windows): verify staged clipboard image contents

refs #4314

* test(windows): safely clean failed clipboard leases

refs #4314
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: preserve request ids in socket error responses

refs #4344

* docs: clarify socket error response limits

refs #4344

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
* fix: reveal selected agent when cycling the sidebar

* fix: reveal agent after endpoint activation
refs #4346

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>
* fix: prevent cursor jumps during synchronized redraws

refs #4303

* fix: settle cursor positions across delayed windows redraws

refs #4303

* fix(windows): hold jump-shaped cursor moves through the max window

* fix: bound windows cursor settling and repaint at its deadline

refs #4303

---------

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
Co-authored-by: JJLiebig <jj@liebig.gg>
Co-authored-by: Axel Karlsson <axelalbertkarlsson@outlook.com>
* test(windows): distinguish clipboard paste origin in input gauntlet

refs #4314

* test(windows): correct gauntlet paste-origin evidence

refs #4314
refs #4303
* fix: detect kiro status from live controls and osc signals

refs #4203

* fix: handle variable-height kiro approval panels

refs #4203

---------

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: detect codex status with custom interrupt keys

* test: remove unverified codex stale-status cases

* fix(detect): match punctuation in codex interrupt hints

Accept parentheses in remapped interrupt binding labels and simplify the cheap prefilter to a single any-gate shared by both manifest copies.

---------

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: preserve delayed mouse reports with confirmed keyboard input

refs #3480

* fix: capture geometry before replaying buffered mouse input

refs #3480

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: keep workspace navigation visible in terminal theme

refs #4300

* fix: clear workspace highlight on directional pane focus

refs #4300

---------

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #4293

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>
* fix: drain event subscriptions and report history loss

refs #4178

Root cause:
Each subscription emits at most one matching event per 100 ms poll, while
the shared event history retains only 512 entries. Bursts therefore build
a backlog, and an evicted cursor silently resumes at the oldest retained
event with no indication that earlier events were lost.

Fix:
Drain the bounded retained batch for lifecycle and agent-status streams.
Check for history loss while holding the same lock used to read events,
then return an events_lost error and close only the affected subscription.
Keep event envelopes, request shapes, endpoint codecs and wait behavior
unchanged. Preserve state filters, initial snapshots, event order and the
existing cadence for snapshot-only subscriptions.

Document resubscription and snapshot recovery in the unreleased API docs.
Add regressions for burst draining, startup-window loss, retention bounds,
status ordering and filtering, and unavailable history.

Validation:
Three socket regressions fail before the fix and pass afterward. Thirty-two
focused API tests and five repeated rounds of socket tests pass. The real
current-master comparison receives 516 of 600 events before the fix and
600 of 600 after it in about 0.97 seconds. A paused reader receives the
explicit error, and a new subscription plus snapshot recovers successfully.

Full native just ci on the dependency-inclusive branch passes 3631 Rust
tests with six default skips, formatting, all-target Clippy, 112 maintenance
tests, six architecture tests and 39 integration-asset tests. All seven
docs contract tests pass. No retries or additional exclusions were used.
Local Windows cross-lint was not run because its SDK is unavailable.

* test: cover subscription isolation across platforms

refs #4178

---------

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #4393

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: confirm closing the last tab in the tui

refs #4379

* docs: clarify last-tab worktree confirmation in translations

refs #4379

---------

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: preserve session layouts across shutdown and restore failures

refs #4320

* test: update subscription fixture for pane restore errors

---------

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #1931
Remove the droid-specific filter that discarded ED3 before PTY output
reached the terminal parser. Keeping stale scrollback beneath replayed
primary-screen frames duplicated the welcome header and old transcript.

Pass the original bytes to the parser and trackers. Add process-aware
regression coverage across PTY chunk boundaries and preserve ED2/ED3
screen-history separation and alternate-screen isolation.

Co-authored-by: ain3sh <ainesh.chatterjee@gmail.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #3338
refs #3990
refs #3916
refs #4104
* fix: stagger restored agent startups

refs #4102

* fix: report startup delay changes requiring restart

refs #4102
refs #1362
refs #4220
* fix: reuse ssh authentication and add in-app mfa recovery

refs #3763

* refactor: move ssh recovery to machine cli

refs #3763
refs #4309
refs #4313
refs #2968
refs #4470

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #4470
* test: wait for complete handoff pid markers

* test: wait for complete handoff pid markers
* fix: prevent cursor flicker on status redraw

* fix: avoid stale cursor during resize
refs #4507
* fix: match navigator search terms independently

refs #4273

* docs: remove redundant navigator search note

refs #4273
* fix: report partial Windows input coverage and clear clipboard for tests

* fix: require evidence from each Windows input channel

* fix: reject clipboard format count errors
* feat!: replace the custom graphics api with optimized native kitty rendering

* fix: enable safe kitty optimizations automatically

---------

Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
refs #4546
refs #4506
* fix: keep copy mode active during projection updates

refs #3812

* fix: preserve linewise selections during projection gaps

refs #3812

---------

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
Panes whose app has not enabled the kitty keyboard protocol received
ctrl+shift+letter as the same C0 byte as ctrl+letter. Encode the chord as
CSI-u instead, matching Ghostty's legacy encoder.

refs #4581

Co-authored-by: ain3sh <ainesh.chatterjee@gmail.com>
refs #4630

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
refs #4446

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
* fix: create a symlink on non-elevated windows in docs test

Windows terminals without Developer Mode or elevation cannot create file
symlinks, so the versions publishing integration test failed with EPERM
before it could reach the non-ordinary-file rejection. Fall back to a
directory junction, which is creatable without elevation and hits the
same rejection path.

* fix: detect docs snapshot reparse points with lstat

Classify entries with lstat instead of the readdir dirent so symlinks and
Windows junctions are rejected regardless of how a runtime classifies
them. This keeps the versions integration test's non-ordinary-file
assertion meaningful on non-elevated Windows, where the fixture can only
create a directory junction.
* fix: refresh host palette on terminal redraw

* fix: count overlapping host palette queries

---------

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
* fix: keep api listener alive after transient accept errors

refs #4601

* fix: drop repeated api accept failure logs

refs #4601
* refactor: extract libghostty-vt binding into ghostty-vt workspace crate

* fix: build libghostty-vt into each build's out dir
* feat: default machine add label to the ssh host

`herdr machine add <ssh-target>` no longer requires `--label`. Without
one, the machine is named after the SSH host with any `user@` prefix
removed, so `herdr machine add dev@workbox` shows up as `workbox`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Apply suggestion from @greptile-apps[bot]

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: make default machine labels unique per session and handle ssh urls

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
* feat: let agents report their own resume command

* fix: keep reported resume commands tied to accepted sessions and current owners
`git apply` by default expects `-p1`, which is the default behavior of
`git diff`, but this can be overridden by config. Specify it explicitly
so it works regardless.
The interactive-shell idle test sent SIGINT as soon as it observed the
shell was busy. That condition can be true before the shell finishes
moving the command into its own foreground process group, so the
interrupt could arrive before the command reset its signal dispositions.
The command then survived in a stale foreground group while the shell
showed a prompt, and the pane was never observed idle again.

Run cat and end it with EOF instead. cat blocks on stdin, so the busy
state is stable, and EOF avoids the interrupt/job-control race.
* feat: support multiple prefix keys

keys.prefix accepts an array in addition to a single string so one
config can define several prefix keys. Every configured prefix enters
the same prefix mode, and the help panel lists them all.

Published keybinding profiles keep the primary prefix as a scalar and
carry the rest in an optional extra_prefixes field so older clients
keep working with the primary prefix.

* fix: reject an empty prefix list on reload

An explicitly empty keys.prefix array now stays empty through config
parsing so validation rejects it and a reload keeps the current
keybindings instead of silently falling back to ctrl+b.
* fix(windows): read agent command lines without PROCESS_VM_READ

Windows process command lines were read by opening each process with
PROCESS_VM_READ and walking its PEB. Hardened runtimes (Electron/Node) and
security products deny that access, so those processes resolved to a bare
`node.exe`/`bun.exe` name with no argv, argv0, or cmdline. A runtime-wrapped
agent launched from such a process was then indistinguishable from an
unrelated runtime process, and the pane stayed on the shell with
`agent_status: unknown`.

Prefer `NtQueryInformationProcess` with `ProcessCommandLineInformation`
(Windows 8.1+), which needs only `PROCESS_QUERY_LIMITED_INFORMATION`, and keep
the existing PEB read as a fallback for processes that do not expose a stored
command line. The fallback still requires `PROCESS_VM_READ`, so this only
widens coverage.

refs #4579

* fix(windows): handle growing command lines before failure test

The retry added for a command line that grows between the size probe and the
read was unreachable. NTSTATUS is signed, so STATUS_BUFFER_OVERFLOW,
STATUS_BUFFER_TOO_SMALL, and STATUS_INFO_LENGTH_MISMATCH are all negative and
were treated as failures by the earlier `status < 0` check.

Check the growth statuses first and retry once with the reported size. Also read
the returned UNICODE_STRING header unaligned, since a Vec<u8> buffer only
guarantees byte alignment.

* test(windows): keep command-line marker test process alive

Passing the marker as a second argument to `ping` let `ping` exit as soon as it
saw one target, so the command-line query could race the process exit. Move the
marker into a `rem` after `&` so it stays in cmd.exe's own command line and
`ping -n 11` keeps the process alive for the read.
* perf: send scrolling pane output as row shifts and skip blank cells

* fix: keep expanded scroll patches disjoint for the fast presentation path
refs #1530
refs #4369
* fix: summarize old servers and saved machines after herdr update

* fix: include reconnect and per-session restart commands in update summary
* fix: keep escape-prefixed terminal key bindings intact

refs #4751

* test: cover escape-prefixed option+backspace binding

refs #4751

(cherry picked from commit 898f733f92)
Merge tag 'v0.9.3' into sync/upstream-0.9.3
Some checks failed
CI / Windows ConPTY package (pull_request) Has been cancelled
Distribution contract / validate (pull_request) Has been cancelled
CI / conventional-commits (pull_request) Has been cancelled
CI / check (ubuntu-latest) (pull_request) Has been cancelled
CI / check (macos-latest) (pull_request) Has been cancelled
CI / check (windows-latest) (pull_request) Has been cancelled
Nix / flake check (pull_request) Has been cancelled
210f3a35be
- Merge upstream v0.9.3 (commit 7b116c05bf)
- Retain FreeBSD platform shims, AGENTS.md, and justfile
- Strip contributor check in root build.rs
- Add FreeBSD target mappings (x86_64-freebsd, aarch64-freebsd) to crates/ghostty-vt/build.rs
- Verified integration::config_file and server::autodetect test suites pass on FreeBSD 15.1
Merge pull request 'sync/upstream-0.9.3' (#16) from sync/upstream-0.9.3 into master
Some checks failed
Close pending-release issues / close (push) Has been cancelled
Trigger Website Deploy / trigger (push) Has been cancelled
CI / conventional-commits (pull_request) Has been cancelled
CI / check (ubuntu-latest) (pull_request) Has been cancelled
CI / check (macos-latest) (pull_request) Has been cancelled
CI / check (windows-latest) (pull_request) Has been cancelled
CI / Windows ConPTY package (pull_request) Has been cancelled
Distribution contract / validate (pull_request) Has been cancelled
Nix / flake check (pull_request) Has been cancelled
CI / conventional-commits (push) Has been cancelled
CI / check (ubuntu-latest) (push) Has been cancelled
CI / check (macos-latest) (push) Has been cancelled
CI / check (windows-latest) (push) Has been cancelled
CI / Windows ConPTY package (push) Has been cancelled
Distribution contract / validate (push) Has been cancelled
Nix / flake check (push) Has been cancelled
adadd96743
Reviewed-on: #16
clawdie changed target branch from ci/freebsd-build to master 2026-10-11 00:38:44 +02:00
clawdie closed this pull request 2026-10-11 12:10:38 +02:00
All checks were successful
freebsd-build / freebsd-15 (build, test & package) (pull_request) Successful in 13m36s
freebsd-build / freebsd-15 (build, test & package) (push) Successful in 13m31s

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
clawdie/herdr!17
No description provided.