Commit Graph
5262 Commits
Author SHA1 Message Date
Mohamed Boudra ad67c7030c docs(plugins): publish client entry guides
Restore the public client-entry reference, migration guide, links, and migration-table drift test when the feature is ready to launch.
2026-09-02 23:08:09 +02:00
Mohamed Boudra 2250148e3a docs(plugins): hold public entry docs until launch
Keep the shipped plugin runtime implementation documented internally while removing the public launch material until the feature is available to users. The companion add-back PR restores these pages and their drift check at launch.
2026-09-02 23:06:09 +02:00
Mohamed Boudra f75dff2322 Require explicit setup for fork pull requests (#4215)
* feat(workspaces): gate fork repository automation

Cross-repository change requests can execute contributor-controlled package hooks even when the setup command comes from the base repository. Persist the checkout provenance and require one explicit workspace-level setup action before repository automation runs.

* fix(workspaces): clarify blocked script errors

* fix(app): keep long toasts readable

* test(server): expect fork repository provenance

* test(server): make setup marker portable

* test(app): retry transient sidebar layout
2026-09-02 20:50:22 +02:00
Mohamed Boudra 2d8ff6f1cf Restore copy actions in web diffs (#4229)
* fix(app): restore diff copy actions on web

The canvas-backed diff owns selection without creating a DOM range, so browser context menus cannot expose copy actions themselves. Route keyboard and context-menu actions through the renderer's canonical source selection instead.

* fix(app): harden web diff copy actions

* fix(app): default split header selection to new pane

* fix(app): isolate nested diff context menus

* fix(app): select available split diff pane
2026-09-02 20:25:55 +02:00
Mohamed Boudra 53d824a320 feat(plugins): split client and server plugin entries (#4206)
* feat(plugins): phase 1 split runtime entries after green gate

The compiler now builds explicit client and server entries, so runtime boundaries are source-owned instead of registration-name filtering. Compiler and runtime tests prove the entry split, directory and suffix boundaries, client Node import errors, migration failure, and client-only operation without a subprocess.

* feat(plugins): phase 2 run client entries after green gate

Explicit client and server contexts replace the mixed plugin context. The app runner owns every client registration and its idempotent removal, including late contributions and composer pills; focused contribution tests prove the removal contract, and all five migrated examples reached running on the isolated worktree daemon.

* feat(cli): phase 3 scaffold runtime split after green gate

The generated project demonstrates the required shared RPC contract, server handler, client surface, and sidebar wiring. The scaffold test and an isolated init, typecheck, install, and running check prove the phase acceptance path.

* docs(plugins): phase 4 publish migration after green gate

Gate: current docs and the paseo-plugin skill describe only explicit client/server entries. The standalone migration guide maps every former registration, and migration-doc.test.ts proves every client add* method remains represented.

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Gate: compiler 13, runtime 24, typecheck, lint, and format passed. The dependency fixture proved node_modules/client was incorrectly treated as a plugin boundary.

* fixup! feat(plugins): phase 2 run client entries after green gate

Gate: client runtime and registry tests, typecheck, lint, format

* fixup! docs(plugins): phase 4 publish migration after green gate

Gate: migration docs test, paragraph audit, typecheck, lint, format

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Gate: compiler organization tests, typecheck, lint, targeted format

* fixup! feat(plugins): phase 2 run client entries after green gate

Gate: shared SDK tests, runtime tests, typecheck, lint, targeted format

* fixup! feat(cli): phase 3 scaffold runtime split after green gate

* fixup! docs(plugins): phase 4 publish migration after green gate

* fixup! feat(plugins): phase 1 split runtime entries after green gate

* docs(plugins): rewrite public plugin docs for runtime entries and mobile guardrails

* fixup! feat(cli): phase 3 scaffold runtime split after green gate

The scaffold now keeps DOM globals out of the program and declares only window.open inside client/web.ts. The scaffold test invokes tsc in a fresh process, proves the generated project passes, and proves a stray document access fails.

* fixup! docs(plugins): phase 4 publish migration after green gate

The internal guide and plugin skill now forbid both the DOM lib and triple-slash DOM references. They direct web adapters to declare only the globals used by client/web.ts.

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Removing the obsolete Babel parser changes the locked npm dependency graph. The macOS Nix desktop gate reported the new fixed-output hash, which this commit records.

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Reject relative imports that escape the plugin root while continuing to skip resolved node_modules internals. The compiler regression test proves the escaped import is rejected and the dependency-internal fixture remains accepted.

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Classify absolute imports and reject plugin-authored paths that escape into node_modules. Dependency internals remain exempt based on their importer path. Red-first compiler regressions cover both bypasses, and the existing dependency fixture remains green.

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Classify canonical esbuild resolution results so dependency-relative and symlink imports cannot escape client/server boundaries. The two compiler regressions failed before the fix and pass afterward.

* test(ci): synchronize flaky state transitions

Wait for repository watcher registration before emitting buffered ref events, let sidebar order polling retry unlaid-out rows, and wait for the inactive browser parking state before screenshot capture. These changes directly address the three observed CI failures; the affected server, Playwright, and desktop browser tests pass locally.

* test(ci): synchronize Mermaid completion layout assertion

The Playwright streaming acceptance test exposed a completion remount between visibility and layout sampling. Check the existing completion promise around the measurement so that transition is not reported as diagram loss.

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Resolve bare package imports before boundary classification so symlinked dependency entries cannot expose server modules to the client bundle. The focused regression proves the bypass and the compiler file passes 20/20.

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Allow canonical paths only within a matching linked package root while preserving runtime and containment checks for imports that leave it. The linked-dependency regression fails before the fix and compiler tests pass 21/21 afterward.

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Reject matching package manifests that contain the plugin or live inside it, so linked-dependency roots cannot exempt plugin or workspace files. The ancestor-manifest regression fails before the fix and compiler tests pass 22/22 afterward.

* fixup! feat(plugins): phase 1 split runtime entries after green gate

Validate plugin-local lexical boundaries before canonical linked-root exemptions and require remembered-root imports to originate inside that root. The linked-root bypass regression fails before the fix and compiler tests pass 23/23 afterward.
2026-09-02 19:11:45 +02:00
fa1f01ebbc feat(app): add fullscreen viewer for Mermaid diagrams on web (#4107)
* feat(app): add fullscreen viewer for Mermaid diagrams on web

Add a fullscreen action to the diagram toolbar that opens the diagram in
a modal ZoomableViewport with free zoom/pan, closable via the close
button, Escape, or clicking outside the diagram. The sandboxed iframe
runtime moves into a shared MermaidIframeRuntime so the inline host and
the fullscreen viewer drive the same renderer.

Fixes uncovered while verifying the feature end to end:

- The runtime measured the rendered SVG with getBoundingClientRect(),
  which depends on the iframe size the host derives from that very
  measurement. Each streaming re-render shrank the reported size by the
  diagram box padding, ratcheting diagrams down to a few pixels. Measure
  the viewBox instead, which is the diagram's own size, and let the SVG
  fill whatever frame the host provides.
- ZoomableViewport's root is flex: 1, so as a flex item its 0% basis
  overrode the inline diagram box height and the box collapsed, scaling
  the diagram tiny and clipping the toolbar unclickable. Size the box
  from its height and keep a minimum tall enough for the toolbar.
- react-native-web's Modal focus trap focuses the first descendant that
  takes focus, which was the diagram iframe; every keystroke then landed
  in the sandboxed frame and Escape never reached the window listener.
  Mark the presentational iframe inert and focus the viewer's content
  layer on mount.

Closes #4106

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(app): exercise Mermaid fullscreen interactions

Cover zoom, pan, outside-click dismissal, and streaming layout through the real browser path. Remove the mocked DOM test that duplicated those behaviors without exercising the viewport or iframe runtime.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-09-02 16:10:26 +02:00
Mohamed Boudra d4841b68ff fix(website): detect the visitor platform during SSR (#4222)
The homepage download CTA was chosen by a client-only hook that started at
"mac-silicon" and corrected itself in an effect, so the server-rendered HTML
said "Download for Mac" for every visitor and only became right after
hydration. On a phone that window is long enough to photograph. Worse, the
detection had no mobile branch at all: Android user agents also say "Linux",
so once hydration did land, a Pixel was offered an AppImage.

Resolve the platform from the request user agent during SSR instead, so the
first paint is already correct. Mobile visitors get the App Store or Play
Store as the primary action and a link to /download for the desktop build,
rather than a .dmg they cannot open.

The markup now varies by user agent, so HTML and server-function responses
carry `Cache-Control: private, no-store` and `Vary: User-Agent`. An absent
cache-control is not no-store — a shared cache may assign heuristic freshness,
and turning on Workers Cache would store a headerless 200 for two hours under
a key that ignores the user agent, letting one Android visitor pin the Play
Store button for every Mac visitor after them.

Also tighten the mobile layout the wrong CTA was sitting in: the primary
action gets its own row so the icon buttons stop orphaning one of themselves,
provider cards drop to a two-column grid, and the hardcoded mobile line break
in the phone showcase gives way to a balanced measure.
2026-09-02 15:46:16 +02:00
Mohamed Boudra ac085d50c6 Make import session one tap away and make the sheet find your session (#4216)
* feat(app): make import session a first-class entry point

* feat(server): improve import session discovery resilience

Search up to 500 persisted candidates per provider and isolate listing failures behind eight-second deadlines so healthy results remain usable. Preserve native persisted title precedence while keeping discovery read-only.

Parsing now continues through each transcript so native titles and the true last prompt are retained; the old early exit made lastPromptPreview equal firstPromptPreview. A cheap record prefilter avoids JSON.parse for unrelated lines during the full scan.

* feat(app): searchable, grouped import session sheet with per-provider errors

The sheet now carries a debounced search field gated on the host's
importSessionSearch feature, grows its per-provider page on demand
(15 -> 45 -> 90 -> 200) instead of capping at the 15 most recent, and groups
unscoped rows by folder under the project name the app knows for that
directory. Worktrees of one project would otherwise all head up as the same
bare name, so a directory below its project root carries the path under that
root beside the name.

A workspace-scoped sheet says so and offers "Show all sessions". Importing a
row from another directory once that is on drops the workspace from the
request, which the daemon would otherwise reject, and routes the user to the
agent's own workspace rather than opening a dead tab in the current one. That
decision lives in resolveImportTarget: a scoped listing is trusted wholesale
because the daemon already matched it realpath-aware, which the client cannot.

A provider that fails now gets its own error row with a Retry that refetches
only that provider, sourced from both a failed request and the daemon's
providerErrors. React Query no longer retries these, so the header spinner
settles once every provider has answered or given up (#2512).

* test(e2e): import session flow with fixture Claude sessions

* fix(app): shorten import sheet scope copy so it fits at phone width

At 390px the scoped subtitle rendered "Sessions in this wor..." — the label,
its action, and the sheet's refresh and close buttons do not share one line at
phone width. The label already sits under the sheet title "Import session", so
"Sessions in this" was repeating context the header had: it becomes "This
workspace" and the action becomes "Show all". The unscoped label still names
the host, which nothing else on the sheet does.

* refactor(app): flat recency-ordered import list with per-row folder label

Grouping by folder buried recency: a busy directory's block of fifteen pushed
a two-minute-old session in a quiet directory below the fold, and the axis a
user is scanning on is when they last touched the session, not where it lives.
The unscoped sheet is now one list in the order aggregateSessionEntries already
produces, and each row carries its folder as a muted third line.

resolveDirectoryLabel stays — it is what keeps two worktrees of one project
apart — and formatDirectoryLabel renders its two parts as the single ellipsised
line a row has room for. A scoped sheet lists one directory, so its rows carry
no folder line at all.

* fix(app): close import sheet before refreshing sessions

Provider-list invalidation waited for every active query before the sheet could close. Mark the disabled picker queries stale after close and navigation so reopening refreshes without delaying the imported agent.

* fix(server): reuse workspaces for session imports

Host-wide imports should join the oldest active workspace for their directory, or restore its archived workspace, instead of minting duplicates. Rollback remains limited to workspace records created by the failed import.

* test(e2e): express the import session journey through a helper DSL

* test(e2e): align sidebar journeys with import entry point
2026-09-02 15:44:44 +02:00
1c960261ac feat(providers): add Gajae Code to the ACP provider catalog (#3471)
* feat(providers): add Gajae Code to the ACP provider catalog

Gajae Code (gjc) ships a conformance-tested ACP agent (`gjc acp`), so it can be
a one-click catalog entry instead of a hand-written custom provider in
config.json. Command and env match what the agent's own installer writes.

* feat(providers): add Gajae Code icon

---------

Co-authored-by: Yeachan-Heo <yeachan.heo@gmail.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-09-02 15:32:23 +02:00
Mohamed Boudra 7838b534a8 Show self-hosted and hosted Hub plans (#4213)
* feat(website): publish Hub pricing options

Present self-hosted and hosted Hub choices together while reading the hosted offer from Hub's public catalog.

* fix(website): require a valid hosted offer

* fix(website): preserve Hub page on catalog failure
2026-09-02 15:05:28 +02:00
Mohamed Boudra ff0171cf7b Make agent tab tooltips compact and informative (#4214)
Join and truncate prompt-derived titles for the visual tooltip, add agent ID and live human activity metadata on a second row, and keep activity subscriptions local to the open tooltip. Preserve the full normalized title as the accessible tab name and cover the behavior through Playwright.
2026-09-02 14:27:18 +02:00
Mohamed Boudra 77aff0f4fb fix(app): stabilize Mermaid streaming lifecycle (#4210)
Drive the streaming assertion from the actual turn lifecycle so iframe replacement at completion is not mistaken for diagram loss. Preserve the cached timeline range during reload reconciliation so a projected message spanning the cache cursor replaces its partial prefix instead of being appended to it.
2026-09-02 13:37:32 +02:00
Mohamed Boudra 708f9260b1 fix(server): disable repository fsmonitor commands (#4208)
A repository-controlled core.fsmonitor command can execute when the daemon refreshes Git state. Opening or reconciling a malicious checkout therefore allows code execution as the daemon user. Force core.fsmonitor=false on daemon-owned Git invocations before repository config is considered.
2026-09-02 13:15:51 +02:00
Mohamed Boudra e34aea206e feat(plugins): add live timeline rows and client slash commands
Plugins can transform live timeline source items at render time, append durable plugin rows from daemon handlers, and register client-only slash commands in the composer.

Related to #3940 and #3952.
2026-09-02 13:12:09 +02:00
Mohamed Boudra 49784fac15 Keep Changes and working diff comparisons in sync (#4199)
* fix(app): keep Changes comparison and diff in sync

Own the working comparison at the workspace checkout so the Changes tree and adjacent working diff share it. Immutable commit diffs remain scoped to their commit SHA.

* docs(app): align working diff ownership notes
2026-09-02 12:38:16 +02:00
Mohamed Boudra 4aab00f267 fix(desktop): use CLI shim for packaged Linux installs (#4207)
Non-AppImage packages install the Electron executable at a stable path, but invoking it through the CLI symlink cannot restart the daemon. Link the bundled CLI shim for those targets while preserving AppImage links.\n\nFixes #4184
2026-09-02 12:30:28 +02:00
Mohamed Boudra de8535c38b Customize top-level sidebar items (#4203)
* feat(app): customize top-level sidebar items

Let users reorder and hide built-in and plugin sidebar rows from Appearance settings while keeping the preference device-local. Add Search as a first-class row and standardize section explanations as header info tooltips.

* fix(app): preserve consecutive sidebar preference edits

Derive each sidebar change from the latest cached settings and retain unavailable plugin slots while editing the visible list. Keep E2E interaction selectors tied to accessible control names.

* test(app): isolate provider settings unit boundary

Keep the legacy provider-section test focused on provider behavior now that its shared section shell can render the settings info control.
2026-09-02 11:42:39 +02:00
Mohamed Boudra d67a6f5f6c fix(release): keep releases draft until manifests are ready (#4201)
Create tag-triggered GitHub releases as drafts and publish them only after the desktop updater manifests are complete, stamped, and uploaded. Preserve beta prerelease semantics and safe retry behavior.\n\nCloses #4183
2026-09-02 11:29:41 +02:00
paseo-ai[bot] 78f7796eb4 fix: update lockfile signatures and Nix hash [skip ci] 2026-09-02 00:19:07 +00:00
Mohamed Boudra 9400a49af6 chore(release): cut 0.7.2 v0.7.2 2026-09-02 02:07:34 +02:00
Mohamed Boudra e9612df862 docs: add 0.7.2 changelog 2026-09-02 01:57:25 +02:00
Mohamed Boudra 8dd4da6ee0 Keep mobile streaming and panel motion stable under JS stalls (#4190)
* fix(app): activate mobile panels after motion settles

Gesture previews were publishing React presentation state and activating retained content before the native motion finished. Keep transient motion on the UI thread and publish the active panel only from the accepted animation completion.

* perf(app): re-render only changed history rows

Every coalesced stream tick re-rendered all mounted history rows because the inverted FlatList recreates each cell with a new index and ref. Keep layout item identity for unchanged rows and memoize the row on it, and resolve tool-call groups through a stable event so the render callbacks stop churning.

* perf(app): count replica row bytes once

Budget accounting measured every stored row of a touched host on each persist through the Buffer polyfill. Cache the UTF-8 length per immutable row and count without materialising bytes.

* fix(app): settle mobile panels on position

Activity now follows the UI-thread position reaching the canonical anchor instead of an animation completion callback. A successful gesture keeps its finishing motion and the matching command adopts it; settlement and command acceptance may arrive in either order.

* fix(app): keep settled panel props across JS stalls

Turn off Reanimated's FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS. Its settled-props collector drops entries older than two seconds before React receives them, so a JS stall across a settle left the overlay display and backdrop opacity reverted on the next commit while the store held the new panel.

* fix(app): reconcile hidden keyboard end on iOS

Only a hidden end event resets the keyboard shift. A late visible end no longer resurrects a keyboard that already dismissed.

* fix(app): focus the replacement input through autoFocus after clearing

Clearing swaps the native input for a fresh instance. Focusing the doomed instance asked Android for the keyboard and then tore the focused view down, which cancelled the show; a JS focus command sent alongside the remount reached a view that was not attached yet and the IME ignored it. Focus and blur requested while the replacement is pending now decide the replacement's autoFocus, which native applies once the view is attached.

* fix(app): revise history rows in every viewport

The history row memo boundary bails out until its item identity changes, but only the native viewport cloned rows flagged by historyRowRevision. On web and desktop a history host whose tool-call group kept updating from the live head rendered stale. Move the revision into useRevisedHistoryRows and run both viewports' history through it. Regression test renders the web strategy with a memoized row and asserts only the revised host re-renders.
2026-09-02 00:52:44 +02:00
Mohamed Boudra 3998ea11d9 Keep large diffs responsive across web and mobile (#4174)
* perf(app): keep large diffs responsive

Render file headers on the canvas and bound expensive text shaping to the active viewport while preserving sticky, hover, and horizontal-scroll behavior. Let native scroll cancellation arbitrate header presses so finger scrolling cannot expand files.

* test(app): assert canvas diff header accessibility

* test(app): assert canvas diff header semantics
2026-09-01 23:52:11 +02:00
Mohamed Boudra ba54575ab7 Show completion times for hidden-prompt turns (#4170)
System-injected prompts have canonical turns but no visible user row, so completed timing was discarded despite an exact end timestamp. Preserve completion metadata with an explicitly unknown duration so the footer can show the truthful timestamp.
2026-09-01 23:24:20 +02:00
Mohamed Boudra 3e59adb4dc Add Claude Fable 5.1 to the model catalog (#4179)
* feat(claude): add Fable 5.1 model

Expose the new 1M-context model through the curated Claude catalog and normalize its dated and context-suffixed runtime IDs back to one canonical entry.

* fix(claude): group Fable models in catalog

* chore(release): cut 0.7.1

* fix(nix): refresh 0.7.1 dependency hash

* test(cli): follow package version in plugin scaffold

* test(cli): keep Claude catalog checks extensible
2026-09-01 21:51:51 +02:00
Mohamed Boudra 640b456915 docs: add 0.7.1 changelog 2026-09-01 20:59:27 +02:00
Mohamed Boudra dd5e8f95b1 Fix graceful daemon shutdown on Windows (#4168)
* test(server): probe supervised Windows cleanup

* test(server): report both cleanup failures

* fix(server): gracefully stop supervised workers
2026-09-01 19:59:03 +02:00
Mohamed Boudra 59661f2bb8 Eliminate recurring cross-platform CI flakes (#4171)
* fix(ci): eliminate recent cross-platform flakes

Synchronize tests on owned state instead of elapsed time or transient identities. Preserve file rename collision safety when platform file IDs are unavailable.

* fix(ci): close follow-up synchronization gaps

Keep fetches in flight through buffered-event classification, scope mock agents to navigation tests, and wait for live workspace hydration before opening agent routes.

* fix(ci): synchronize browser lifecycle boundaries
2026-09-01 19:25:16 +02:00
Mohamed Boudra 06fae60809 Prevent oversized assistant messages from crashing the timeline (#4166)
* fix(app): cap oversized assistant messages

A single assistant message can expand into enough rendered Markdown nodes to crash the renderer. Limit the Markdown input while preserving the complete timeline value and report its full byte size.

* fix(app): bound oversized stream processing

Cap the render input before paced reveal and defer full-message byte counting until completion. Reuse the existing grapheme boundary policy so capped text never ends in a partial glyph.

* fix(app): preserve capped text without segmentation

Hermes lacks Intl.Segmenter, while the shared reveal boundary intentionally returns zero without it. Keep that contract and fall back locally to a surrogate-safe 32K prefix.
2026-09-01 18:06:25 +02:00
JunsandMohamed Boudra 95575ad05a fix(omp): honor configured timeout while waiting for ready (#4143)
* fix(omp): honor configured timeout while waiting for ready

* fix(omp): increase ready timeout to 20 seconds

* docs: keep OMP timeout policy in one place

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-09-01 17:19:56 +02:00
Mohamed Boudra 7ea9286aa4 fix(app): keep agents running when image viewer closes (#4161)
The shared image lightbox handled Escape after the global shortcut dispatcher had already routed the same key to agent interruption. Register the viewer with the established web overlay owner so dismissal takes first refusal while ordinary Escape interruption remains intact.
2026-09-01 16:17:47 +02:00
Mohamed Boudra 07125d2c02 Let Git plugins prepare themselves during installation (#4158)
* feat(plugins): support prepared Git installations

Let Git plugins declare explicit preparation commands without making package installation the default. Keep installation transactional, make plugin trust explicit, and use one canonical source reference for monorepos.

* fix(plugins): parse Windows source references
2026-09-01 16:12:23 +02:00
Mohamed Boudra 0c38749c38 fix(server): rewind paginated Codex threads (#4119) 2026-09-01 07:43:47 +02:00
Matt Cowgerandpaseo-bot[bot] ecec33265e feat(pi): add active-turn steering via native steer RPC (#3752)
* feat(pi): add active-turn steering via native steer RPC

* fix(pi): clear queued steering before interrupt

---------

Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
2026-08-31 21:10:27 +02:00
paseo-ai[bot] 22463bb7e5 fix: update lockfile signatures and Nix hash [skip ci] 2026-08-31 17:36:52 +00:00
Mohamed Boudra c56638ea8c chore(release): cut 0.7.0 v0.7.0 2026-08-31 19:25:32 +02:00
Mohamed Boudra 185ab3f300 docs: prepare v0.7.0 changelog 2026-08-31 19:20:58 +02:00
Matt Cowger 1694828275 fix(opencode): show child session prompts (#4055)
Show OpenCode child-session user prompts even when the text part has no completion timestamp.
2026-08-31 18:35:28 +02:00
74a377ff6a fix(server): keep daemon alive when JSONL RPC stdin hits EPIPE (#4048)
* fix(server): keep daemon alive when JSONL RPC stdin hits EPIPE

A dead Claude/OMP child currently turns stdin.write() EPIPE into
uncaughtException and kills the daemon. Catch the write, listen for
stdin errors, and close that transport instead.

Closes #4047

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(server): reproduce JSONL RPC stdin EPIPE

* test(server): gate native EPIPE fixture on POSIX

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-31 15:35:34 +02:00
Mohamed Boudra 63923fdd07 Keep Android timeline still when tapping text (#4090)
* fix(android): keep timeline still when tapping text

Selectable Android text takes touch focus. React Native then scrolls focused children using untransformed coordinates, which moves inverted timelines even though the user did not scroll.\n\nSkip that auto-scroll only for touch-focused, selectable, non-editable text in inverted vertical scroll views, preserving normal focus navigation and editable inputs.

* test(e2e): isolate PR pane fixtures from bots
2026-08-31 12:10:40 +02:00
Mohamed Boudra 11e76f6655 fix(server): resume agents cleanly after failed turns
Track each foreground run start as pending, started, or failed so a previous turn error cannot reject a newly accepted prompt. Includes a regression for resuming after a failed turn.
2026-08-31 12:10:34 +02:00
Mohamed Boudra 4a3e6dea63 Increase mobile content text to 16px (#4111)
Keep mobile interface chrome at 15px while defaulting readable content to 16px. Migrate existing mobile 15px content preferences once while preserving later explicit choices.
2026-08-31 11:58:42 +02:00
paseo-ai[bot] f35d860725 fix: update lockfile signatures and Nix hash [skip ci] 2026-08-31 08:17:46 +00:00
Mohamed Boudra 95f4eb7577 chore(release): cut 0.7.0-beta.3 v0.7.0-beta.3 2026-08-31 09:52:59 +02:00
Mohamed Boudra fcd81f591e chore(release): carry forward 0.7.0-beta.2 version 2026-08-31 09:46:56 +02:00
Mohamed Boudra b0fe4efc8c docs: add v0.7.0-beta.3 changelog 2026-08-31 09:45:26 +02:00
Mohamed Boudra f2f93087ed docs(website): refresh product comparisons
Reframe the pages around verified product differences while emphasizing local ownership, privacy, extensibility, and deployment flexibility.
2026-08-30 23:48:54 +02:00
Mohamed Boudra 73a5e6c63e feat(website): expand homepage product story 2026-08-30 23:48:54 +02:00
Mohamed Boudra fa53ba8f93 feat(website): refine responsive product mockups
Keep desktop and mobile scenes visually consistent while improving phone depth, diff realism, alignment, and interaction polish.
2026-08-30 23:48:54 +02:00
Mohamed Boudra 375e9b3e53 feat(website): rebuild homepage product mockups
Replace static captures with live, responsive scenes that demonstrate building, reviewing, shipping, and extending work across desktop and mobile.
2026-08-30 23:48:54 +02:00