Commit Graph
8523 Commits
Author SHA1 Message Date
github-actions[bot] 49f57f83b4 release: v1.4.183 v1.4.183 2026-08-15 02:29:49 +00:00
github-actions[bot] 1214dc8494 release: v1.4.183-rc.0 v1.4.183-rc.0 2026-08-14 08:24:26 +00:00
Jinjing e534802b04 test: add golden e2e tests for agent TUI launch and shell recovery (#14258)
* test: add golden e2e tests for agent TUI launch and shell recovery

Add test fixtures and E2E tests to verify agent TUI functionality:
- Stub agent implementation supports cross-platform execution (Unix/Windows)
- Test verifies multiline composer with Shift+Enter support in agent TUI
- Test verifies clean shell resumes after agent exit without state leakage

* test: add golden e2e tests for agent TUI launch and shell recovery

Add agent TUI launch and shell-recovery tests to the golden (release-blocking)
E2E suite, covering agent initialization and shell availability after agent
exit. Improve escape sequence handling in the stub agent to prevent stray key
reports from contaminating test output. Add terminal input readiness checks to
ensure commands execute reliably before verification.

* test: coerce golden stub stdin chunks for type-aware lint

Node types the stdin data event as string | Buffer even after
setEncoding('utf8'), so restrict-plus-operands failed CI.

* test: fix golden stub agent Windows batch files and add Ctrl+C support

- Store batch files with CRLF to avoid Windows 512-byte parser boundary bug
- Handle Ctrl+C (0x03) in raw mode as alternative to Ctrl+D (0x04)
- Update release notes documenting golden test skip behavior on older tags

* Remove Windows batch file gitattributes workaround

The -text whitespace=cr-at-eol rule preventing CRLF conversion for
.cmd files is no longer needed. Allow batch files to use normalized
line endings.

(cherry picked from commit 70abf5cacc)
2026-08-13 22:44:40 -07:00
Jinjing d5cc067560 test(e2e): add golden E2E tests for workspace session management (#14304)
* test(e2e): add golden E2E tests for workspace session management

- Restore exact file and terminal state after quit/relaunch
- Verify terminal file link activation and external edit detection
- Test worktree creation and switching with isolated terminals
- Isolate test repo paths between concurrent CI runs with UUIDs

* Add platform-aware marker echo command utility

- Create splitMarkerEchoCommand() to generate shell commands that
  safely echo test markers across Windows and Unix platforms
- Split markers into prefix/suffix fragments so output assertions
  prove execution, not just shell echo-back
- Consolidate SORTABLE_TAB export and improve tab bar locator logic
- Refactor terminal link helpers to extract client point calculation

(cherry picked from commit b8d6b21dfa)
2026-08-13 22:44:06 -07:00
Jinjing 8d86b08e16 test: add golden E2E tests for source control workflows (#14260)
* test: add golden E2E tests for source control workflows

- Tests core source control interactions: file edit/save, commit staging, and diff viewing
- Integrated into CI/CD pipelines for Linux, macOS, and Windows
- Includes helper utilities for test setup and worktree management

* test(e2e): verify golden commit author and fix test flakiness

- Configure git author name/email at worktree level during setup
- Verify commits are made with correct author details in assertions
- Add explicit timeouts to file visibility waits and git status polling
- Fix test ordering to seed edits after source control is open
- Simplify git status refresh logic to rely on automatic updates

* Add rollback to createGoldenWorktree on setup failure

Cleanup callbacks only register after setup succeeds. When a config
command fails, the half-built worktree and branch leak into later
test runs, causing flakiness. Now we roll back immediately and
re-throw the setup error.

* test(e2e): match explorer rows after the git status badge appears

The golden file-save spec used an exact /^README.md$/ filter. After save,
the explorer row text becomes "README.md M", so reopen clicked nothing.

* test: strengthen golden worktree setup verification

- Track working directory in git call inspection to verify correct execution context
- Verify user.name/email config applies to worktree-specific settings, not repo
- Add exhaustive setup call sequence assertions to catch setup/rollback leaks

(cherry picked from commit e84fb46eaf)
2026-08-13 22:44:06 -07:00
Jinjing 9926a64b83 Add golden E2E tests for fresh terminal and shell commands (#14302)
* test(e2e): add golden tests for fresh terminal and shell commands

Adds regression tests for terminal initialization in fresh profiles and shell command execution to the golden test suite, integrated across Linux, macOS, and Windows CI.

* test(e2e): bracket shell command output between markers

The echoed command can wrap or be clipped by the buffer tail. Bracket output between begin and end markers to reliably identify real output, and strip ANSI escape sequences that interfere with parsing.

(cherry picked from commit e7b85266f5)
2026-08-13 22:44:05 -07:00
Jinjing a144a7fcfc test(e2e): stabilize triaged release failures (#14242)
* test(e2e): stabilize triaged release failures

* rm file

(cherry picked from commit 1d2b8c7f42)
2026-08-13 22:43:50 -07:00
Jinjing 537896f1bc fix(ci): skip missing golden scripts on older release tags (#14267)
Cut Release is dispatched from main but checks out the tagged tree.
Cherry-pick tags such as v1.4.182-rc.1 do not define
test:e2e:windows-fresh-startup-golden, so the Windows golden job failed
with ERR_PNPM_NO_SCRIPT. Run tag-optional goldens with --if-present.

(cherry picked from commit dd63d35d09)
2026-08-13 22:43:50 -07:00
Jinjing ddb3913052 Move worktree labels to right badge rail with truncation tooltips (#14313)
* refactor(palette): move worktree labels to right badge rail with tooltip

Move worktree and branch names from the tab title line to a dedicated right-side badge rail, preventing long titles from being truncated. Add smart tooltips showing full names when truncated, and distinguish between workspace names and branch names based on whether they're auto-generated labels.

* fix(palette): disconnect worktree rail ResizeObserver on unmount

Move truncation observation into a layout effect so React Doctor sees a cleanup path and the subscription cannot leak after unmount.

(cherry picked from commit d957e1c0f5)
2026-08-13 22:43:29 -07:00
Jinjing 14f126ea03 Fix terminal split source incarnation and rejection cleanup (#14238)
* fix(terminal): fence split source incarnation

* fix(terminal): retire rejected split safely

- Track retired rejected PTYs to prevent synthetic exits from landing after
  split rejection completes.
- Validate splits using persisted incarnation IDs only, allowing restored
  sessions without incarnation maps to work correctly.
- Reduce stop timeout from 10s to 2s to avoid stalling on unreachable hosts.

(cherry picked from commit 00cab82fc0)
2026-08-13 22:43:29 -07:00
Jinwoo Hong 8588311601 Fix paired web creation failure handling (STA-4024, STA-4025, STA-4063) (#14100)
(cherry picked from commit de729d6067)
2026-08-13 22:43:29 -07:00
Jinwoo Hong ae1277cf5a Use provider-neutral Opus alias in orchestration guide (#14119)
(cherry picked from commit d349f9a972)
2026-08-13 22:43:28 -07:00
Jinwoo Hong 610fa4cdb8 fix(browser): disable unsupported FedCM (#14023)
(cherry picked from commit 9a81577e91)
2026-08-13 22:43:28 -07:00
Brennan Benson eb6893594a fix(terminal): require agent identity for guarded sends (STA-4028) (#14092)
* fix(terminal): require agent identity for guarded sends (STA-4028)

Quarter-circle spinner glyphs (U+25D0-U+25D3) started classifying a title
as "working" in #13925, and that status alone authorized guarded agent
sends — which auto-submit with Enter — into any pane whose TUI animates
those generic progress frames.

Keep the glyphs as an activity signal, but stop treating a title whose
only agent evidence is a quarter circle as proof an agent owns the pane:
send authorization now falls through to recognized-agent identity in the
title or a recognized foreground process. Braille-spinner behavior is
unchanged.

* fix(terminal): preserve verified managed busy identity

* fix(terminal): bind busy identity to process incarnation

* chore(test): avoid duplicate terminal gate suite

(cherry picked from commit cb41f3c5f4)
2026-08-13 22:43:28 -07:00
Brennan Benson 4c3865feb9 fix(browser): guide Google sign-in after cookie import (STA-4019) (#14085)
* fix(browser): guide Google sign-in after cookie import

* fix(browser): show runtime name in import guidance

* fix(browser): honor host display labels in import guidance

(cherry picked from commit 564968c31e)
2026-08-13 22:43:28 -07:00
Brennan Benson a3bf95792c fix(terminal): repaint a recovered remote pane from the host's retained buffer (#14095)
* fix(terminal): repaint a recovered remote pane from the host's retained buffer

A remote-runtime pane that loses its stream re-subscribes, but the recovery
subscribe only carries new bytes. When the host's push snapshot is empty --
an idle pane, or one whose PTY has exited and is preserved with its buffer --
the transport dropped it and nothing re-armed the restore, so the pane stayed
blank until a visibility flip issued the tagged snapshot request. That is why
switching worktrees once "fixed" it.

Emit onStreamRecovered from the recovery subscribe path only, and mark the
hidden-output restore needed so the pane pulls the buffer the host still holds.
The initial subscribe is untouched: it already carries the host snapshot, and
re-arming there would cost every pane a redundant restore request on open.

* perf(terminal): avoid duplicate recovery snapshot replay

(cherry picked from commit bd12934362)
2026-08-13 22:43:25 -07:00
Brennan Benson 9d1bf556fb fix(terminal): never wipe a painted pane for a snapshot that carries no image (#14099)
* fix(terminal): never wipe a painted pane for a snapshot that carries no image

A hidden-output restore that comes back as a success frame with an empty image
was still applied. The normal-buffer replay opens with \x1b[2J\x1b[3J\x1b[H, so
it cleared screen and scrollback and painted nothing in their place -- turning a
host that had nothing to say into a blank pane.

An empty image is the absence of an answer, not proof the pane is empty, so keep
the frame the user can still see. Retry and banner behavior are unchanged: an
empty image still counts as a successful, non-bannered recovery.

* test(terminal): prove imageless restore preserves painted buffer

(cherry picked from commit a2c9f7e52b)
2026-08-13 22:43:25 -07:00
Neil ae579b9ac6 fix(terminal): retain alt frames through park reveal (#13882)
* fix(terminal): repaint an alt frame the fit never lands for

#13014 skips a too-wide alt frame on snapshot replay and relies on a post-fit
repaint. For a pane visible but permanently below the 48x24px fit floor,
readProposedTerminalCols is forever undefined, so skipIfTargetUnknown drops the
frame — and the only compensating repaint lives in a safe-fit continuation that
is failed rather than run for such a pane. The frame is lost until the user
widens the pane.

Adds a deferred repaint gated on display:none rather than on target-unknown,
preserving #13014's no-clip guarantee for a pane that later fits narrower.

Does NOT fix artificial-opencode-terminal-load.spec.ts:761. Two open concerns:
the repaint waits out the full 40-frame safe-fit retry budget (~1.3s) against
that spec's own 2s restore budget, and the cold-park reveal path at
pty-connection.ts:8222/8289 still has no deferral net.

Co-authored-by: Orca <help@stably.ai>

* fix(terminal): restore the deferred PTY input hop

Inlining forwardPtyInput into the onData handler dropped the
deps.deferPtyInput dispatch, leaving the callback and its type declared
and supplied but never called. Link-click mouse suppression silently
stopped withholding mouse-report frames, so a click in a mouse-tracking
TUI reached the PTY and the link-open fallback never fired.

Covers both branches, which had no test at all.

* fix(terminal): retain alt frames until final fit

* fix(terminal): preserve park intent across effect replay

* test(terminal): satisfy native static analysis

* fix(terminal): consume park intent after layout replay

* fix(terminal): re-read park intent instead of caching it per pane

useTerminalParkMountIntent cached park intent in a ref for the lifetime of
the component. The ref was never load-bearing: React finishes the render
phase before any effect runs, so StrictMode's passive-effect replay already
observes the same render-phase value. What makes the reveal work is reading
at render time rather than at connect time, which a plain call already does.

The ref did go stale. The pane lifecycle effect re-runs on [tabId, cwd] for
the same component instance, so a worktree path or startupCwd change
resupplied mountFollowsTerminalPark: true long after the park reveal, since
the post-replay consume clears the per-run ptyDeps copy and not the ref.
Each spurious run re-armed the pre-paint snapshot prefetch.

Also scope the post-replay consume behind a tested one-shot helper so splits
created after the restored-layout replay keep ordinary reconnect semantics,
and correct two comments that described the removed ref.

---------

Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
(cherry picked from commit ef8eea51af)
2026-08-13 22:43:24 -07:00
m4air a50d49936c Narrow paired browser link fix to registration race
(cherry picked from commit 2f85dda183)
2026-08-13 22:43:21 -07:00
Jinjing 0cb4fb188b Fix remote server browser tab fallback behavior (#14194)
* fix(browser): require runtime browser capability

* fix(browser): reuse capability verdict and exclude floating terminals

Cache the runtime browser capability check across multiple remote port opens instead of checking for each port independently. Prevent floating-terminal workspaces from routing to remote browsers.

* fix(browser): pin remote pane link opens to owning runtime

Remote pane link opens must route to the pane's runtime, never the client.
Fails if the workspace has moved to a different host while the pane still
displays a remote page, preventing silent misrouting to a dev server.

* trim comments

(cherry picked from commit 939acf1c2b)
2026-08-13 22:42:31 -07:00
Jinwoo Hong b869f04595 fix(browser): route remote terminal links to owning host (#14117)
(cherry picked from commit e8350f1990)
2026-08-13 22:42:31 -07:00
Jinwoo Hong 15156a433a Gate paired web creation actions by provider (#13909)
(cherry picked from commit ebe5125476)
2026-08-13 22:42:31 -07:00
Jinjing 858bad1930 Fix fsync of read-only files on POSIX (#14235)
* fix(files): fsync read-only files on POSIX

* test(e2e): add golden E2E tests for POSIX profile index fsync

Validates that profile index files are properly persisted on POSIX systems, including with restrictive umask settings. These are release-blocking golden tests for Linux and macOS.

* test(terminal): wait for fish child ownership before stdin write

Fish 4.8 withdraws DECSET 2031 before spawning the child, so the
shell-contracts harness could send hello into an intermediate prompt
and hang waiting for CHILD-READ. Wait for the child's CHILD-READY
marker and answer split DA1/CPR/OSC queries across chunk boundaries.

* test(e2e): verify profile index persists to disk with restrictive umask

Strengthen the POSIX fsync test to verify the rebuilt index is actually
written to disk and has correct permissions under a restrictive umask,
not just cached in memory.

(cherry picked from commit 7c93aed6dc)
2026-08-13 22:41:59 -07:00
Neil 18f96e156e fix(windows): restore fresh-profile startup after durable fsync (#14173)
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: DHTheOne <238933622+DHTheOne@users.noreply.github.com>
Co-authored-by: Anton Tupitsyn <70199858+PLUTONYY@users.noreply.github.com>
Co-authored-by: 7loop <48346764+7loop@users.noreply.github.com>
(cherry picked from commit e8044b1b30)
2026-08-13 22:41:31 -07:00
Brennan Benson c2178a0be3 fix(browser): fence the cookie-clear fallback to the pre-clear snapshot (STA-4170) (#14343)
* fix(browser): fence the cookie-clear fallback to the pre-clear snapshot (STA-4170)

The post-rejection fallback re-read the live cookie jar and removed everything
removable at that moment, while restore only ever covered the pre-clear
identity snapshot. A cookie that arrived mid-clear -- a login the user had just
completed -- was therefore deleted with no identity able to put it back, and a
later removal failure still reported "existing cookies were restored".

Fix the removal plan at the same point as the identity snapshot so the mutated
set can never exceed the restore set. Arrivals are not touched at all, which
matches what the successful bulk-clear path already does.

* test(browser): lock same-coordinate arrival rollback to the pre-clear value (STA-4170)

(cherry picked from commit e799259d3b)
2026-08-13 22:41:29 -07:00
Brennan Benson f65932699e fix(browser): fail-closed cookie clear after a partial import wipe (STA-4090) (#14191)
* fix(browser): fail-closed cookie clear after a partial import wipe (STA-4090)

A rejected bulk clear plus a later per-cookie removal could permanently
delete cookies that were already gone. Snapshot partition-complete
identities before mutating, keep the bulk clear, and restore through CDP
so a failed import never silently drops existing cookies.

* fix(browser): preserve exact cookie clear identities

* fix(browser): abort unrepresentable cookie clears

* fix(browser): skip excluded-only cookie clears

(cherry picked from commit 93334dc53f)
2026-08-13 22:41:29 -07:00
Brennan Benson da5cd8e101 perf(browser): clear cookies in one bulk call that excludes the Google family (STA-4065) (#14131)
* perf(browser): bulk clear cookies when an import excludes nothing (STA-4065)

PR #14086 replaced the bulk clear with one Electron cookies.remove() per
removable cookie so partitioned excluded cookies survive an import. That is
required whenever something must be preserved, but it also runs when nothing
is excluded, where a single clearStorageData is equivalent and far cheaper:
421ms -> 7.3ms at 1k cookies and 1764ms -> 20.1ms at 3k on Electron 43.

The fast path is gated on the same unfiltered cookies.get() the exclusion
predicate already reads, which an Electron fixture now proves returns
partitioned cookies, so "no exclusions in the snapshot" means "nothing in the
jar to preserve".

* fix(browser): protect cookie clear fast-path race (STA-4065)

* test(browser): keep the no-bulk-clear assertion honest after the clearData switch

The mocked session still exposed clearStorageData, so asserting it was never
called could no longer fail once the fast path moved to clearData.

* docs(browser): stop the fallback comment from asserting a rollback

The per-cookie path's rollback is being removed by STA-4061; the comment only
needs to say the fallback re-removes what survived.

* test(browser): keep the STA-4061 rollback fixture on the per-cookie path

The bulk fast path clears a jar with no excluded cookie in one call, which
would have made every assertion in the partition-rollback fixture vacuous.
Give it a live Google cookie so the partial-failure clear still runs, and
assert the bulk call count is zero so a future widening fails loudly.

* perf(browser): always bulk clear cookies, not only when nothing is excluded

The fast path only fired when the jar held no Google cookie, but this import
exists for Google, so a Google cookie is normally present and the common case
still paid one native remove per cookie. Measured on Electron 43, clearData
excludeOrigins preserves the whole google.com registrable family -- host,
leading-dot, subdomain and partitioned cookies -- so the bulk call is safe with
cookies to keep, and the gate was never load-bearing for preservation.

Drop the caller-supplied exclusion predicate so the preserved set has exactly
one source of truth: a predicate that disagreed with NON_TRANSPLANTABLE_DOMAINS
would have deleted cookies the bulk call is meant to keep. The per-cookie loop
stays as the fallback for a rejected bulk clear, carrying the same exclusion.

* fix(browser): re-read the cookie jar after a rejected bulk clear

clearData can empty part of the jar before rejecting, so the per-cookie
fallback was working from a snapshot taken before the attempt: it retried
removals for cookies that were already gone and could not see cookies that
arrived during the clear. Re-read on rejection only.

Also repairs three fixtures that mocked the session with clearStorageData
after the call moved to clearData. The missing method threw, the catch
swallowed it, and every one of those tests silently asserted per-cookie
behaviour while believing it covered exclusion. Records the registrable-domain
invariant at NON_TRANSPLANTABLE_DOMAINS, since excludeOrigins derives one
origin per entry, and extends the real-Electron fixture to prove http-only and
domain-scoped Google cookies survive alongside the partitioned one.

(cherry picked from commit e5906837e4)
2026-08-13 22:41:29 -07:00
Brennan Benson 3a14e8e3fc fix(browser): never resurrect cookies after a failed import clear (STA-4061) (#14132)
* fix(browser): never resurrect cookies after a failed import clear (STA-4061)

removeAllCookiesExcept rolled a partial clear back by rebuilding each removed
cookie with cookies.set. Electron's cookies.get() omits partitionKey and
cookies.set() drops it, so a non-Google CHIPS cookie that had been removed came
back as an ordinary unpartitioned cookie — silent, restart-proof auth-state
corruption on a code path that reports failure.

The exclusion comment already stated the invariant ("Electron cannot round-trip
partition identity"); it was only applied to the Google family. Extend it to the
rollback: a failed clear now stays failed, which is retryable, instead of
reconstructing cookies whose identity cannot be reproduced.

* test(browser): require partitioned cookie removal (STA-4061)

(cherry picked from commit bc2e30000b)
2026-08-13 22:41:29 -07:00
Brennan Benson 3f7ee3d494 fix(browser): preserve partitioned Google cookies on import (#14086)
(cherry picked from commit fc7c2a1cd5)
2026-08-13 22:41:29 -07:00
OrcaWin 09ec516ae5 fix(editor): index WSL watcher aliases per batch (#14015) 2026-08-12 03:24:31 -07:00
github-actions[bot] ad6f8011e2 Update README downloads badge 2026-08-12 09:33:52 +00:00
OrcaWin e5cd5bf542 fix: decouple Floating Workspace shell selection (#13995) 2026-08-12 02:09:57 -07:00
Jinwoo Hong 70ad65fc94 Fix paired remote HTML browser ownership and focus (#13876)
* Fix paired remote HTML browser preview

* Register paired HTML preview reliability gate

* Scope browser worktree selection guard

* Harden paired HTML preview ordering

* Simplify paired HTML preview ownership

* Record final paired HTML preview evidence

* fix(remote): simplify browser preview ownership

* test(remote): refresh HTML preview evidence

* fix(remote): reconcile browser create ordering

* fix(remote): guard browser focus through reconcile

* fix(remote): bound delayed browser focus

* fix(remote): guard browser focus context

* test(remote): record final HTML preview evidence

* fix(remote): keep HTML previews in background

* test(remote): cover browser focus modes

* test(remote): record focused browser contracts
2026-08-12 02:02:10 -07:00
Jinwoo Hong 346e59c879 fix(renderer): keep commit tooltip lines intact (#14000) 2026-08-12 01:10:47 -07:00
Brennan Benson 36d45af062 feat(browser): guide Google sign-in after cookie imports (STA-3811) (#13666) 2026-08-12 00:53:02 -07:00
Neil 9c091cf77e chore(perf): add renderer agent-status benchmark harness (#13905)
Splits run-idle-cpu-benchmark.mjs into a scale fixture, an in-page timing
probe, and process sampling, and records a measured origin/main baseline so
the agent-status batching slice has an auditable before.

The agent-status write workload is not included: it needs setAgentStatuses,
so it lands with the store slice.
2026-08-12 00:37:48 -07:00
Brennan Benson 2249330acf fix(browser): bulk clear cookies during native import (#13966)
* fix(browser): bulk clear cookies during native import

* fix(browser): separate Google cookie import warning

* fix(browser): report encrypted Google cookie exclusions

* fix(browser): skip key lookup for excluded cookies

* test(browser): cover excluded-cookie key bypass

* perf(browser): keep plaintext key scan cheap
2026-08-12 00:33:50 -07:00
NeilandOrca a90a18d43d perf(renderer): anchor spinner phase from animationstart only (#13987)
Co-authored-by: Orca <help@stably.ai>
2026-08-12 00:30:14 -07:00
Jinjing a81224614a fix(agents): detect a live OpenCode pane from its native OC | session title (#13957)
* fix(agents): detect a live OpenCode pane from its native OC | session title

OpenCode publishes `OC | <session>` as its OSC title, which carries no
agent-name token. detectAgentStatusFromTitle gates status on a whole-token
name match, so it returned null and every status consumer read a live
OpenCode pane as a plain shell: no "Send notes to" entry, no title-derived
sidebar row, and a title that the runtime's agent-presence check scored as
neutral. Identity already resolved (getAgentLabel returns OpenCode); only
activity was missing.

Treat the native marker as a live idle agent, placed after the spinner and
glyph checks so the decorated frames pinned by #8940 keep their status, and
accept it in the send-readiness gate the way Claude's U+2733 prefix is
accepted -- only a running OpenCode TUI ever publishes it.

* fix(agents): require spaced `OC | ` marker for native OpenCode detection

Unspaced pipes like `OC|Build` match other tools and would mistakenly
route non-OpenCode panes as send targets. Enforce literal ` | ` as
OpenCode emits it. Also clarify that only spinner decorations carry
working status, not keywords in the session summary.

* fix(agents): require OpenCode foreground process to validate native mark

OpenCode's native `OC | ` title marker now requires an active OpenCode process
to authorize agent sends, preventing false detection when the marker is left on
shell prompts. Extends wrapper prefix matching (ssh, tmux, etc.) and spinner
glyph support. Adds permission-prompt blocking signals for guarded writes.
2026-08-12 00:07:59 -07:00
Jinwoo Hong fd2afc16c8 Fix paired web Add Project folder browsing (#13885) 2026-08-11 23:25:50 -07:00
Jinwoo Hong c45c806220 fix(orchestration): close federated-read benchmark socket (#13939) 2026-08-11 23:19:07 -07:00
Jinwoo Hong 7319d59a10 Make worker completion and cleanup authoritative (#13927)
* fix: require authoritative worker completion verdicts

* Harden federated settlement replay

* fix(orchestration): reconcile dead retained workers

* docs: record SSH worker release coverage

* test(e2e): exercise worker settlement and release CLI

* docs: register combined orchestration CLI oracle

* test(orchestration): pin pre-ack attachment state
2026-08-11 23:06:12 -07:00
Brennan BensonandOrcaWin 4b9fb46646 fix(agent-hooks): stop rewriting typed Prime commands (#13906)
* fix(agent-hooks): preserve typed Prime commands

* test(wsl): enforce Prime bridge exclusion

---------

Co-authored-by: OrcaWin <alpha-eng@stably.ai>
2026-08-11 22:34:54 -07:00
Neil 9e18e1456b fix(workspace-emoji): keep the ':' shortcode suggestions scrolled to the highlight (#13969) 2026-08-11 22:18:26 -07:00
Neil 3d4c968e9b perf(renderer): drop redundant worktree card cache-TTL subscription (#13903)
promptCacheTtlMs was a third store subscription for a field the card
already reads via foundation.settings; derive it instead.

Does NOT bundle the 26 foundation selectors as originally planned.
Measured on this store with React (150 cards, 400 unrelated writes,
26 keys): 26 separate useAppStore hooks 100.7ms; one useShallow bundle
402.5ms (4.0x worse); one bundle with a non-allocating keyed compare
141.5ms (1.4x worse). zustand v5 shallow() rebuilds two Maps from
Object.entries per compare, and a bundle must still build the whole
projection every notification, so collapsing cheap selectors only
trades away useSyncExternalStore dispatches that are cheaper than the
object it allocates. Listener count would have improved 26 -> 1 while
the hot path got slower.
2026-08-11 22:13:39 -07:00
NeilandOrca 971d9548b5 docs(agent-status): make design references self-contained (#13902)
docs/design/agent-status-over-ssh.md was cited from ~10 source files but
does not exist in the repo. Replace each pointer with the invariant the
code actually relies on so the knowledge survives without the doc.

Renderer-side citations (useIpcEvents.ts, agent-status-types.ts) are left
for the concurrent batching change that owns those files.

Co-authored-by: Orca <help@stably.ai>
2026-08-11 22:13:35 -07:00
NeilandOrca 0079623f26 Fix reveal active workspace needing multiple clicks (#13926)
Co-authored-by: Orca <help@stably.ai>
2026-08-11 22:10:44 -07:00
Jinjing 5bee7b5ce9 P1 STA 3887 design Preview Kitty IME (#13940)
* fix(terminal): carry kitty flags through Preview snapshots and pair rele

Preview was omitting the live kitty mirror from the IME bridge and dropping kitty flags from snapshots, so every commit was evaluated at flags 0. A TUI that negotiated bit-3 (report_all_keys_as_escape_codes) would receive the legacy raw text it declined.

Now the snapshot carries proven kitty flags beside their sequence boundary, the forwarder reads flags once per commit, and bit-1 (report_event_types) commits are paired with exactly one release regardless of keyup/insertText ordering. Snapshot authorities expose only the active screen's proven flags, so an old host's absent field stays unknown rather than downgraded to a manufactured zero.

* fix(terminal): sync kitty flags and IME releases across snapshots

* trim wordinesss

* fix(terminal): settle owed IME release before fresh same-key press

When a keyup is lost and the same key is pressed again, settle the stale
record's owed release instead of discarding it — this maintains correct
IME state during recovery. Also refine Kitty flag propagation to only
carry proven baselines across snapshots, and tighten related comments.

* fix(terminal): gate kitty flags on sequence boundaries

- Remote snapshots only include flags when seq is present
- Daemon uses parsed flags value when defined
- Ensures correct flag ordering in snapshot replay
2026-08-11 22:00:44 -07:00
NeilandOrca 5ea7df1a5b fix(terminal): make DECSET 2031 subscriptions silent (#13904)
fish arms `CSI ?2031h` before painting each prompt and withdraws it when it
hands the tty to a child — a ~1ms window. Orca answered that subscribe with
`CSI ?997;Nn` across a 1-3ms renderer hop, so the reply landed after the
withdrawal and was read as stdin by the next child, corrupting `brew`/`npx`
`[y/N]` prompts.

The reply is not stale by Orca's own view when written (measured
staleReplies: 0), so no suppress-the-stale-reply scheme can close this — the
information needed to suppress does not exist yet. Nothing asked for the reply
either. The Contour spec says a terminal "should only send out the DSR when the
palette has been updated"; Ghostty (Termio.zig:729 — force=true reachable only
from the ?996n DSR), iTerm2 (VT100Terminal.m:995 — flag only) and xterm.js
(InputHandler.ts:2035 — flag only) all emit nothing on the DECSET. So stop
entering the race: record the subscription, answer nothing.

Of 17 real programs measured under a pty, only fish, tmux, claude and opencode
subscribe; none block on a reply, and answering produces one redundant palette
re-query and zero rendering difference. tmux is the only one that sends `?996n`,
which Orca still answers.

- Subscribes are record-only at all four emitters (live scan, hidden-gate fact,
  parked byte watcher, parked responder — the last is deleted, it only replied).
- `?996n` answers, the subscription registry, and the theme-flip push are
  unchanged. `paneLastThemeMode` is still seeded at subscribe so the next
  appearance re-apply is not read as a flip.
- Replay grammar carries `?2031l` alongside `?2031h`, so a late-attaching remote
  client no longer registers a subscription the TUI already retired.

Also closes fish-integration gaps found alongside: `unset` (which fish lacks)
becomes `set -e` on paths parsed by the client's login shell, `config.fish` is
parsed for agent-home detection, and bracketed-paste startup delivery is made
consistent across local/daemon/relay.

Regression test drives real fish 4.7.1 under node-pty and asserts on what the
child process reads; it fails against pre-fix code with the exact payload from
the issue. CI installs fish 4 and fails loudly rather than skipping.

Closes #9993

Co-authored-by: Orca <help@stably.ai>
2026-08-11 21:16:36 -07:00
Brennan Benson 137e724119 fix(agent-title): treat Claude Code quarter-circle spinners as working (#13889) (#13925)
* fix(agent-title): treat Claude Code quarter-circle spinners as working

Claude Code 2.1.228 swapped its busy OSC title spinner from braille
(U+2800-U+28FF) to quarter circles (U+25D0/U+25D1). Orca recognized a busy
Claude title only by braille codepoints, so the new frames matched nothing.

The summary-bearing busy frame ("<glyph> Say hi in one word") carries no
"claude" name token, so it resolved to no-status. The tracker's "idle or
permission followed by no-status means the agent exited" rule then fired
mid-turn, confirmPtyAgentExit confirmed it, and the chat surface routed
exitChat -- kicking the tab to the terminal view on every message.

Widen the accepted glyph set via a shared containsAgentSpinnerGlyph helper.
Agent-specific braille frame shapes (Grok, Pi, synthetic Cursor) stay pinned
to their own glyph set.

Fixes #13889

* fix(agent-title): satisfy static analysis and trim scope
2026-08-11 21:13:27 -07:00