Render optimistic turn feedback before host acknowledgement and roll it back on rejection. Reconcile iOS keyboard offsets from the native transition end event so JS contention cannot leave the composer displaced.
* feat(server): expose daemon Git pressure metrics
Separate limiter queue wait from Git execution time and report subscription ownership so accumulating work is visible in the existing runtime log.
* fix(server): collect subscriptions in agent metrics
Reuse the existing agent snapshot during runtime flushes so WebSocket shutdown does not require an additional AgentManager method call.
* test(server): retry transient hub cleanup
* fix(app): open notifications on the right host
Agent notifications previously omitted workspace ownership, so a cold target host was treated as missing and fell back to its empty home route. Carry the authoritative workspace and keep older notifications on a target-host resolver until lookup is conclusive.
* fix(app): separate notification and agent URL routing
Notifications use their authoritative workspace target directly. Stable agent URLs remain server-and-agent targets whose workspace is resolved by the agent route.
* fix(protocol): preserve notification workspace targets
Both attention message variants retain workspaceId through outbound validation so notification clicks receive the authoritative route target.
* test(app): use workspace-scoped notification target
* test(server): give notification agents workspace targets
* test(app): target notification workspace in navigation e2e
* feat(desktop): open existing agents from links
Register a stable agent deep link and route it through the existing Desktop window. Add a matching CLI command that resolves the local server and activates the requested agent without creating or messaging it.
* fix(desktop): recover agent link delivery
* fix(app): restore archived agents from History
History navigation lost the explicit archived-agent intent during tab reconciliation, and workspace recovery stopped after restoring the workspace. Preserve the selected tab and recover its provider session as one action while serializing provider resume with timeline hydration.
* fix(app): preserve archived agent recovery invariants
* fix(server): preserve timeline hydration call shape
* fix(app): retain agent tabs through lookup
* fix(server): upgrade in-flight timeline broadcast
Timeline catch-up treated the first unmatched optimistic prompt as an insertion boundary, which could move later acknowledged prompts behind assistant output. Apply canonical entries directly and preserve submission slots during replacement.
The desktop daemon resolved the CLI through a packaged module entrypoint that is not an executable outside the archive. Publish the existing bundled shim as the daemon's authoritative CLI path so terminal hooks use a callable command.
Make the host runtime own session and setup replicas for the registered host lifetime. Provider remounts can then reattach without clearing directory snapshots or timeline cursors.
Keep service route choices independent of daemon transport and persist the selected route per host. Use the shared web overlay stack so menus, tooltips, and toasts layer predictably.
Track proxy route changes from the Git branch rather than the workspace title to avoid transient service health changes.
* feat(files): edit workspace files on web
Keep source buffers synchronized with host file changes and require an explicit overwrite or reload when revisions diverge.
* feat(panels): surface and protect modified tabs
Expose tooltip and modification state through the generic panel boundary so tabs can show stable metadata and guard every close route consistently.
* fix(tests): use portable fake timeout handle
* fix(files): harden editor conflict handling
Preserve modified panel state across tab eviction, use precise revisions for optimistic writes, coalesce concurrent file watchers, and localize the editor interface.
* fix(files): close editor concurrency gaps
Coalesce clean reloads, preserve subscriber identities and file permissions, suspend pending saves during close confirmation, and carry precise revisions through file reads.
* test(files): expect read revision metadata
* starr
* fix(server): honor service port allocator contracts
* fix(server): pass workspace context to port scripts
* fix(server): cancel released service port plans
* test(server): support Windows port allocator fixtures
* docs(worktrees): clarify shell-less portScript execution
Canonical provider message IDs and optimistic client IDs occupy different namespaces. Preserve both identities for deterministic reconciliation while retaining a dated content fallback for older daemon timelines.
* fix(server): release resources held by idle agents
Keep unarchived agents resumable while closing their provider runtimes after two minutes. Active agent schedules keep runtimes resident.
* fix(server): preserve resumable agent state
* fix(server): resume agents when listing commands
* fix(server): preserve collected agent interactions
Keep a small non-authoritative view of the last focused chat so the app can paint it before the daemon finishes revalidation. Bound persistence to one focused agent per host and evict whole host entries to limit storage and serialization work.
Module-level style composites could materialize the temporary adaptive theme before persisted settings loaded. Keep Unistyles reads in render and guard against eager module-scope access.
* fix(app): keep focused agent timelines live
Window focus was conflated with app visibility, so switching OS windows could remove the selected timeline subscription. Separate those signals, grace every visibility-driven removal, and cover retained history until authoritative catch-up completes.
* fix(app): keep timeline catch-up failures non-blocking
* fix(app): surface timeline catch-up failures
* fix(app): preserve file preview refocus
* fix(app): preserve optimistic catch-up flow
* fix(projects): detect when projects become Git repositories
Project identity was coupled to Git placement, while non-Git roots were dropped by session-scoped observation. Keep identity tied to the selected root and observe Git transitions daemon-wide so empty projects update without rehoming workspaces.
* fix(projects): preserve metadata across Git read failures
Refresh archived workspace facts before persistence and treat only confirmed non-repositories as non-Git so transient failures cannot rewrite stored project metadata.
* fix(projects): close project update races
* fix(projects): refresh checkout metadata when reopening folders
Persist worktree ownership separately from workspace kind and gate exact-root project creation on stable host identity. Refresh active and archived records so missed Git transitions cannot return stale checkout descriptors.
* test(projects): accept Windows aliases for repaired roots
* test(server): retry transient Windows cleanup locks
* fix(projects): propagate project metadata refreshes
Project-only Git transitions now fan out workspace updates for legacy clients. Explicit project creation refreshes stored kind, and equivalent cwd spellings reuse existing workspace records.
* fix(projects): refresh worktree source project kind
* fix(projects): preserve exact-folder runtime isolation
* fix(projects): preserve exact cwd across worktree lifecycle
* fix(projects): harden exact-folder worktree flows
* fix(projects): derive exact cwd from matched path identity
* fix(projects): preserve nested worktree lifecycle
* refactor(projects): centralize workspace placement
* test(e2e): verify isolated server ports
* fix(projects): preserve placement reshape compatibility
* fix(projects): validate created worktree placement
* fix(projects): preserve placement through workspace lifecycle
Archive and recovery were rediscovering or guessing checkout roots instead of consuming the persisted workspace placement. Make the record authoritative for exact cwd, backing worktree, and source repository, and classify stale paths before Git reconciliation.
* fix(worktrees): preserve source checkout root
Convert Git's common administrative directory back to the source checkout root when legacy archive placement is reconstructed.
* fix(worktrees): compare filesystem identities
Resolve discovered worktrees and teardown locations through the shared realpath-aware matcher so Windows short and long path spellings cannot split placement identity.
* fix(worktrees): centralize path containment
Route worktree ownership, listing, resolution, and deletion through the realpath-aware containment primitive so Windows path aliases cannot be filtered by an earlier raw prefix check.
* fix(worktrees): remove duplicate ownership discovery
* test(e2e): isolate daemon restart ownership
* fix(worktrees): make lifecycle operations transactional
* fix(workspaces): share git watches by cwd
* test(worktrees): make teardown proof portable
* fix(sync): integrate project updates with directory owner
* fix(workspaces): close reconciliation edge cases
* refactor(sync): remove duplicate project reconciliation
Keep workspace and project deltas behind the host directory transaction, with owner-boundary coverage for snapshot replay and queued full reconciliation.
* fix(sync): buffer project updates before hydration
Start the workspace transaction with the online connection epoch so project broadcasts cannot publish a partial directory before the authoritative snapshot commits.
* fix(desktop): keep browser tabs connected across workspaces
Electron can replace a guest WebContents when a retained browser tab is reparented. Re-register each attachment and keep background actionability checks running so agent browser tools retain the tab through workspace eviction.\n\nCover the full app, daemon, Electron, and MCP path in the existing desktop CI job.
* fix(desktop): launch Electron E2E reliably on Linux
CI Electron must receive --no-sandbox before the app starts because the hosted runner cannot use Electron's bundled SUID sandbox helper. Forward explicit dev-runner arguments and fail readiness waits as soon as a child exits.
* fix(desktop): preserve active browser on repeated registration
* fix(desktop): keep browser keyboard attachment idempotent
* fix(desktop): wait for E2E bridge readiness
* fix(desktop): close E2E logs after output drains
* Reapply "Always revalidate desktop updates before install"
This reverts commit 623c05aa4d.
* fix(desktop): make update revalidation safe on quit
Updater-triggered quits now bypass normal quit handling, and manifest revalidation gives up after five seconds without allowing a late install.
* fix(desktop): preserve fail-closed update installs
Keep cached updates deferred when quit-time validation is offline, and report validation timeouts separately from superseded releases.
* fix(desktop): preserve updater quit behavior
Automatic installs remain silent without relaunching, updater handoff is bounded, and background preparation failures remain visible without pinning manifest checks.
* fix(desktop): keep AppImage updates manual
Preserve the AppImage safety exemption by skipping ordinary quit-time installation while retaining the explicit Update now path.
* fix(desktop): serialize update preparation
* fix(desktop): recognize macOS updater quit handoff
* refactor(forge): forge-neutral foundation (GitHub-only)
Decouple git-hosting from GitHub behind a neutral abstraction (issue #1616), GitHub-only for now; existing GitHub behaviour is unchanged.
- Forge manifest, neutral ForgeService contract, forge registry + resolver, and a client forge-module registry.
- GitHub code renamed to the neutral shape; PR/Issue attachment wording preserved.
- forge.search.response enums parse tolerantly (unknown kind/auth state degrade instead of breaking the client).
- createPullRequest reports typed CLI/auth errors instead of a generic message.
- forge-resolver host/remote caches are LRU-bounded.
- Forge host trust is explicit: only a known cloud host or a CLI-authenticated host is ever talked to; an unauthenticated GitHub Enterprise host fails resolution instead of routing to github.com.
- Docs: forge-providers guide, glossary and i18n forge-copy conventions, architecture and rpc-namespacing terminology.
- Vitest React Native mocks (unistyles, svg, linking, lucide) consolidated into shared aliased test-stubs.
* feat(forge): GitLab adapter, forge-aware UI, pipelines and approvals
GitLab adapter over the glab CLI on the neutral contracts: MR status, forge-aware UI, pipeline tree, and N-of-M approvals.
- threadIsResolved is part of the neutral timeline item.
- Pipeline load failures show an error instead of an empty section.
- Manual pipeline jobs render as pending.
- Fork/detached MR head pipelines are fetched by MR iid (glab ci get --merge-request).
* feat(forge): Gitea family adapter (Gitea, Forgejo, Codeberg)
One adapter over the tea CLI serving Gitea, Forgejo, and Codeberg on the neutral contracts.
- CI status aggregates commit statuses and Actions runs together.
- Gitea's terminal "warning" state maps to failure on server and client.
- Gitea Actions check details are reachable from the PR pane by workflowRunId.
* refactor(forge): localize compatibility handling
* test(forge): expect normalized GitLab facts
---------
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
* fix(desktop): keep browser input out of the composer
Unhandled webview keys could be redispatched into the active host window, allowing agent Enter to submit a draft prompt. Give pages first refusal for ordinary shortcuts and contain automation at the guest boundary.
* fix(desktop): tighten browser shortcut validation
* fix(desktop): respect browser shortcut ownership
* fix(desktop): retain browser keys across windows
* fix(desktop): scope browser webviews by host
* Reshape browser shortcut ownership
Use the browser webview registry as the single guest identity authority, scope browser operations to their host window, publish chord continuations only while pending, and restore focus to the originating browser after command center dismissal.
* Fix host-scoped browser shortcut follow-ups
* Fix browser keyboard review follow-ups
* Fix browser keyboard lifecycle regressions
* Fix browser shortcut review regressions
* Fix desktop browser review regressions
* Fix browser shortcut frame regressions
* Fix rebase integration regressions
* Preserve browser-native shortcut ownership
* Isolate browser shortcuts and automation by context
* fix(workspace): keep focus mode scoped and easy to exit
Route focus mode through the active workspace so persisted state cannot hide chrome on settings or other screens. Add a visible exit control and keep desktop window chrome aligned and visually quiet.
* fix(app): clarify muted chrome semantics
Pi and OMP share only the JSONL child-process transport while retaining provider-owned launch, RPC, runtime, session, history, and permission behavior. Removes captured fixtures in favor of typed harnesses and real-provider coverage.
Closes#2006Closes#2060
* fix(desktop): keep sign-in popups connected
Turning every window-open request into a workspace tab severed the opener relationship required by popup authentication flows. Keep script-created and POST-backed opens as secured child windows while ordinary links continue to use workspace tabs.
* fix(desktop): keep Shift-click links in workspace tabs
Electron reports both popup windows and Shift-clicked links as new-window. Use popup features or a named target to preserve script popups without bypassing Paseo tab state for ordinary links.
* fix(desktop): tighten popup profile handling
* fix(desktop): preserve popup feature intent
* fix(desktop): match browser popup heuristics
* fix(app): restore missing workspaces from History
Workspace and agent archival are separate lifecycles. Carry restore intent from History so closed agents can reopen archived workspaces without changing ordinary navigation.
* fix(app): wait for workspace hydration before restore
* fix(app): preserve History agent unarchive
* fix(app): reopen archived History agents outside active directory
History entries are not merged into the active session maps. Carry the row archive state through explicit restore intent so live workspaces still reopen without broadening ordinary navigation.
* fix(app): ignore stale History archive state for active agents
A cached History row can outlive a successful reopen. When the workspace exists, live session state now wins so an active agent is not interrupted by another refresh.
* fix(app): reopen every selected archived History agent
History entries without workspace IDs returned before restoration, and a second archived agent sharing an in-flight workspace restore was dropped. Preserve both agent-only and deferred reopen intent.
* fix(app): require explicit workspace recovery
* fix: preserve workspace recovery contracts
* fix: preserve workspace recovery compatibility
* fix: preserve recovered workspace session state
* fix: preserve terminal navigation timing
* fix(server): preserve successful workspace recovery
* fix: preserve workspace recovery intent
* fix(settings): show daemon update failures
React Native web ignores Alert.alert, so failed remote updates reset to an enabled button without any user-visible explanation. Keep updater progress and failure as explicit rendered state, including the daemon's error, and cover the real browser-to-daemon failure path.
* test(settings): harden daemon update regression
* fix(settings): disable Desktop-managed daemon updates
Desktop-bundled daemons advertised npm self-update even though the install-origin checks always rejected it. Report Desktop ownership to clients, render actionable guidance, and refuse stale requests before touching npm.
* test(desktop): exercise packaged app startup
The previous smoke exited before IPC, window creation, and preload execution, so a broken packaged preload could still pass. Launch the normal app and observe its renderer bridge and managed daemon through CDP instead.
* test(desktop): preserve Linux sandbox in smoke
Configure the unpacked artifact's chrome-sandbox helper with the permissions Electron requires, while keeping sandboxing enabled so preload failures remain observable. Bound startup probes and include process logs in daemon timeout failures.
* ci(desktop): keep packaged smoke on releases
Remove the temporary pull-request artifact build after it validated the Linux launch path. Keep the real packaged smoke in the native desktop release matrix.
* ci(desktop): gate packaged smoke by changes
Run the Linux real-artifact smoke in pull-request CI when packages/desktop changes, while leaving the regular desktop unit-test matrix unconditional.
Adding or cloning a project now registers it and opens workspace setup
instead of creating a workspace implicitly. Keep Add Project independently
mounted from Search so closing one cannot control the other.
* Pin android-sdk to 21.0 and unify Java on 21 for mise
The `.tool-versions` `android-sdk latest` pin had resolved to the
ancient `1.0` cmdline-tools bundle, whose sdkmanager (3.6.0) predates
the `emulator` package and fails with `Failed to find package
emulator`. Pin `android-sdk 21.0`, point the hardcoded install paths
in `.mise.toml` at it, and add `cmdline-tools/21.0/bin` to PATH so
sdkmanager and avdmanager resolve.
Also unify the Java version on 21: `.tool-versions` already pinned 21,
but `.mise.toml` overrode it to 17. A local `npm run android` Gradle
build succeeds on 21.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Document iOS simulator and Android emulator local dev setup
Add local-dev docs for running the app against a worktree daemon:
- development.md: prerequisites for the ios-simulator preview service
(Xcode, an iOS runtime, automatic CocoaPods install), the
xcode-select/simctl troubleshooting fix, and a "Running the iOS app
on a local simulator" section covering `npm run ios` and pointing
the app at a worktree daemon via EXPO_PUBLIC_LOCAL_DAEMON.
- android.md: a "Prerequisites (local dev)" section (mise java 21 +
android-sdk 21.0, sdkmanager components, AVD creation) and a
"Running on an emulator against a worktree daemon" section covering
REACT_NATIVE_PACKAGER_HOSTNAME and EXPO_PUBLIC_LOCAL_DAEMON=10.0.2.2
for reaching the host daemon.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Give full Intel x86_64 emulator setup commands in Android docs
Greptile flagged that the arm64-v8a -> x86_64 substitution for Intel
Macs was only a parenthetical. Provide a complete, copy-pasteable
x86_64 command block instead of asking readers to hand-edit the arm64
one.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* feat(desktop): share persistent browser data across tabs
Keep browser sign-ins and site storage across tabs and app restarts, with a Settings action to clear the shared profile.
* fix(settings): prevent duplicate browser data clears
* fix(desktop): complete browser data cleanup
Clear legacy per-tab profiles after upgrades and localize the browser data settings in every supported language.
* fix(desktop): close browser profile cleanup races
* fix(chat): allow failed turns to be forked
Failed turns can end in Paseo-generated timeline items without provider
message IDs. Anchor forks to canonical timeline positions while retaining
legacy boundaries for compatibility.
Place the fork summary before the new prompt and delimit it as structured
chat history.
* fix(chat): tighten fork boundary handling
* feat(subagents): archive finished children and show native names
Keep native provider sessions intact while letting users clear completed children from the track. Persist dismissed provider child IDs so history replay does not restore them.
* fix(subagents): cover persistence and naming edge cases
* fix(subagents): preserve active descendants and native names
* fix(subagents): retain dismissed timelines and trim paths
* fix(subagents): retain history across hydration
* test(subagents): expect normalized native descriptions
* fix(subagents): separate hidden rows from retained history
* fix(subagents): preserve restored hidden tabs safely
* fix(subagents): integrate archive with run state
* test(codex): expect normalized child name
* fix(subagents): retain dismissed tabs on reload
* fix(subagents): hide finished native agents locally
Keep the header action presentation-only so it does not mutate agent lifecycle or expand the runtime protocol.
* fix(subagents): humanize native agent names
* fix(subagents): preserve names in Codex history
* fix(subagents): retain hidden rows across reloads
* fix(server): prevent hidden Codex subagents and stuck turns
Codex can announce native children only through its mirrored lifecycle stream, while rejected interrupts previously looked like successful local cancellation. Preserve those child announcements and keep manager state active until the provider acknowledges cancellation.
* fix(server): block actions after rejected cancellation
A provider can accept a turn before publishing the turn ID needed to interrupt it. Keep that interval non-cancelable, and prevent reload, replacement, or rewind from proceeding without an acknowledged cancellation.
* fix(server): surface rejected agent cancellations
Replacement prompts and Stop requests could appear accepted after the provider kept ownership of the active turn. Complete replacement cancellation before detaching the stream, and return cancellation failures through the client response.
* fix(server): handle turn completion during cancellation
* fix: finish cancellation lifecycle handling
* fix(server): close remaining cancellation races
* fix(server): settle autonomous cancellations
* fix: honor cancellation failures at call sites
* refactor(server): centralize agent run state
* fix(server): keep pending runs isolated from stale events
* fix: surface remaining cancellation failures
* fix(server): narrow cancellation error handling