Commit Graph
100 Commits
Author SHA1 Message Date
Mohamed Boudra 685e86cffc refactor(app/e2e): rewrite settings-navigation spec to zero raw locators (#726)
Replace 21 raw page.locator/getByTestId/getByText calls in the spec body
with named DSL operations in helpers/settings.ts. Each test body now reads
as prose: open settings, navigate to section, expect content.

New helpers: openCompactSettings, expectCompactSettingsList,
expectSettingsSidebarVisible/Hidden/Sections, goBackInSettings,
expectSettingsBackButton, clickSettingsBackToWorkspace,
verifyLegacyHostSettingsRedirect, openCompactSettingsHost,
expectHostSettingsUrl, expectAddHostMethodOptions, fillDirectHostUri,
expectDirectHostFormValues, expectDirectHostSslEnabled,
expectDirectHostUriValue/Hidden, expectDiagnosticsContent,
expectAboutContent, expectGeneralContent.

Export requireServerId from sidebar.ts so helpers encapsulate serverId
logic — spec has no direct env reads.

Also fix pre-existing typecheck error in use-keyboard-shortcuts.ts:
cast action.route to the expo-router Href type at call sites.
2026-05-05 19:58:55 +07:00
Mohamed Boudra fedf155efd refactor(app): replace screen test slop batch 2 with proper coverage (#725)
Deletes four screen-level .test.tsx files (2600+ lines of vi.mock + JSDOM
slop) and replaces each with verified coverage:

- sessions-screen.test.tsx: covered by archive-tab.spec.ts which exercises
  the sessions screen via openSessions() with real agents
- workspace-draft-agent-tab.test.tsx: covered by new-workspace.spec.ts
  "redirects to optimistic draft tab before agent creation resolves"
- new-workspace-screen.test.tsx: covered by new-workspace.spec.ts (main
  submit, branch selection, PR selection, optimistic draft tab) plus
  new-workspace-picker-item.test.ts (pickerItemToCheckoutRequest)
- project-settings-screen.test.tsx: covered by project-config-form.test.ts
  (all round-trip string/array lifecycle semantics) and projects-settings.spec.ts
  (save flow with passthrough field preservation)

Extracts syncPickerPrAttachment from new-workspace-screen.tsx into a new
pure module new-workspace-picker-state.ts with 5 zero-mock unit tests
covering: initial PR selection, branch selection without change, PR
replacement, PR removal on branch switch, and no-duplicate guard.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 634a9f1e9a refactor(app): replace 4 component test slop files with pure module extractions (#724)
Delete message-input.test.tsx, left-sidebar.test.tsx,
agent-stream-view.test.tsx, and agent-panel.test.tsx — all heavy
vi.mock + JSDOM + toHaveBeenCalledWith slop.

Coverage preserved by extracting the testable derivations:

- agent-stream-view-data.ts: isSameAssistantBlockGroup,
  getAssistantBlockSpacing, resolveInlineWorkingIndicatorItemId —
  14 pure unit tests, zero mocks
- message-input-state.ts: computeCanStartDictation (dictation readiness
  gate) — 7 pure unit tests, zero mocks

Remaining behaviors confirmed covered by existing E2E:
- left-sidebar subscription-while-hidden → sidebar-workspace.spec.ts
- agent-panel render isolation + archived agent store hygiene → archive-tab.spec.ts
- message-input attachment menu / submit icon → workspace-setup-streaming.spec.ts
2026-05-05 19:58:55 +07:00
Mohamed Boudra 79dac91a7a chore(app): clean up e2e helpers — delete duplicates, dead code, and redundant seeding (#723)
- Delete clickNewTabButton (duplicate of clickNewChat) and clickNewTerminalButton (duplicate of clickNewTerminal); update all call sites
- Rename clickTerminal → clickNewTerminal to match clickNewChat naming pattern
- Delete waitForLauncherPanel (deprecated no-op)
- Delete waitForAgentFinishUI and getToolCallCount (dead exports never imported)
- Remove ensureE2EStorageSeeded, assertE2EUsesSeededTestDaemon, and related helpers from app.ts — the paseoE2ESetup auto-fixture seeds via addInitScript on every navigation, making these redundant
- Simplify gotoAppShell to a one-liner; simplify gotoHome to use .or() instead of three-way if-else chain
- Strip try/catch self-heal from ensureHostSelected — the fixture guarantees preferences alignment, so the workaround is never needed
2026-05-05 19:58:55 +07:00
Mohamed Boudra b2af00b037 test(app): triage desktop test files — delete 16-mock component slop, tighten attachment store (#721)
* test(app): triage desktop test files — delete 16-mock component slop, tighten attachment store assertion

Removes desktop-updates-section.test.tsx (16 internal mocks, JSDOM, toHaveBeenCalledWith chains on component renders).
Tightens desktop-attachment-store.test.ts: toHaveBeenCalled() → toHaveBeenCalledWith(attachment).

* refactor(app): extract daemon management toggle coordinator with unit tests

Fills the coverage gap left by deleting desktop-updates-section.test.tsx.
Extracts executeDaemonManagementToggle from useDaemonManagementToggle — pure
async coordinator with injected deps (no vi.mock). Unit tests verify the three
key invariants: settings persist before stop, stop is skipped when not
desktop-managed, and start/stop are invoked on enable/disable.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 652793e00a refactor(app/e2e): migrate workspace-cwd spec to withWorkspace fixture (#722)
Drops the per-test manual boilerplate (connectWorkspaceSetupClient,
createTempGitRepo, seedProjectForWorkspaceSetup, openProject,
openHomeWithProject, navigateToWorkspaceViaSidebar, try/finally cleanup)
in favour of the withWorkspace fixture landed in #717.

Both tests — main checkout and worktree — verified green locally.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 5da0423e48 refactor(app): extract composer-actions module with pure tests (#720)
Move composer cancel/queue/attachment/dispatch orchestration out of
composer.tsx into a React-free actions module. The module takes its
dependencies (send client, queue writer, stream writer, attachment
persister, image picker) as injected ports, so the new
composer-actions.test.ts can drive every action with inline fakes —
zero vi.mock of internal modules, zero JSDOM, zero React.

The old composer.test.tsx (heavy mocked component test) is removed
and replaced with composer-actions.test.ts (31 unit tests).

Also extract isWorkspaceAttachment / userAttachmentsOnly /
workspaceAttachmentToSubmitAttachment from composer-workspace-attachments.tsx
into a sibling .ts so the actions module (and composer-attachments.ts)
can use them without dragging React/RN/lucide into a pure test graph.
2026-05-05 19:58:55 +07:00
Mohamed Boudra a978865f39 refactor(app): extract resolveAgentForm pure reducer from use-agent-form-state (#719)
Moves all preference-resolution logic into a pure `resolveAgentForm(state, action)` reducer
with a discriminated-union action type. The hook becomes a thin React container: it holds state
via `useReducer`, dispatches actions, and owns the hydration-ref timing logic.

Removes the `__private__` export and the vi.mock-heavy live test in favour of direct pure-function
unit tests (53 tests, zero vi.mock of internal modules).
2026-05-05 19:58:55 +07:00
Mohamed Boudra 1955fa6371 refactor(app): extract keyboard shortcut routing into a pure function (#718)
Replace 8-mock hook test (expo-router, layout, platform, navigation,
4 stores) with a pure unit test of the routing decision. The hook now
reads pathname/layout/key, calls routeKeyboardShortcut, and dispatches
the resulting ShortcutAction — no behaviour change.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 5a63bc56f4 refactor(app): make use-agent-input-draft storage injectable (#716)
Extract DraftStorage interface and createAgentInputDraftCore factory
to a new use-agent-input-draft-core.ts. Pure helper functions (resolveDraftKey,
resolveEffectiveComposerModelId, etc.) move there too, breaking the test
file's transitive dependency on AsyncStorage and useAgentFormState.

The test now imports directly from the core module, uses a Map-backed
in-memory storage, and has zero vi.mock calls. Tests assert behavior
("save then load returns the same draft") rather than call counts.
2026-05-05 19:58:55 +07:00
Mohamed Boudra cb4051f4ea feat(app/e2e): introduce withWorkspace fixture and DSL helpers (#717)
Adds a `withWorkspace` Playwright fixture plus composable helpers
(permissions, sidebar, composer, agent-stream, settings) so specs read
as user-level intent. Migrates workspace-lifecycle and settings-host-page
to the new DSL as proof.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 0a84c613f7 test(app): tighten weak assertions in utils tests (#714)
Replace toBeDefined/toBeTruthy guards with concrete shape assertions
using toContainEqual(expect.objectContaining(...)) in diff-highlighter
tests, and toMatch(/^script-draft-\d+$/) for the ID check in
project-config-form tests.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 6bd5d4c410 refactor(app): extract pr-pane derivations into pure utils and unit tests (#713)
Move getStateLabel and getActivityVerb out of pr-pane.tsx into pr-pane-data.ts
so they can be tested without JSDOM, React, or vi.mock. Add exhaustive unit tests
for both helpers alongside the existing mapPrPaneData/formatAge/deriveAvatarColor
coverage. Delete pr-pane.test.tsx — the component test was asserting on derived
label/icon strings that are now covered by pure function tests.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 90c7e591e8 refactor(app): assert store state rather than mock call counts in store tests (#715)
Rewrites two store tests to verify observable state instead of implementation-level call counts.

navigation-active-workspace-store: the "persists" test now uses a functional in-memory AsyncStorage mock that retains written values across vi.resetModules(), then rehydrates a fresh store instance and asserts the resulting selection state matches what was written.

checkout-git-actions-store: removes toHaveBeenCalledWith/toHaveBeenCalledTimes assertions on client methods; replaces with getStatus() assertions that reflect the store's actual state after each action completes or fails.
2026-05-05 19:58:55 +07:00
Mohamed Boudra fd30eafafc refactor(app): fix type-aware lint errors in UI components (#710) 2026-05-05 19:58:55 +07:00
Mohamed Boudra 8d3946c36c perf(cli): run CLI E2E tests in parallel (#708)
* perf(cli): run E2E tests in parallel via worker pool

The custom CLI test runner ran 35 tsx test files sequentially, making the
cli-tests CI job the longest in main CI (~17 minutes). Each test file
already isolates its own daemon (ephemeral port + tmp PASEO_HOME), so
parallelism was just gated by the runner.

Replace the sequential recursion with a fixed-size worker pool (default
concurrency=4 to match GitHub Actions standard runners; override via
PASEO_CLI_TEST_CONCURRENCY). Buffer per-test stdout/stderr and flush as
a contiguous block on completion so concurrent output stays readable,
and report per-test wall clock plus the five slowest tests.

Local wall clock drops from ~12-15 minutes serial to ~2:49 with
concurrency=4. The slowest single test (05-agent-run, 49s) is now the
floor; CI should land near 4-5 minutes.

* fix(cli-tests): deflake 30-chat under load and shard CI across 3 runners

`chat wait` reads the latest message id and then subscribes for newer
messages. Under CI load the subprocess takes >1s to bootstrap, so the
old test's 250ms head start before posting "second message" raced
against that read. When the post landed first, the subprocess saw the
second message as latest and timed out waiting for a newer one. Replace
the brittle delay with a post-and-race loop: every iteration posts a
fresh "second message" and races a 250ms tick against the wait promise,
so whichever message lands after the snapshot wakes wait deterministically.

CI was also slower than local (10.3min vs 2.8min). On 4-vCPU GHA
runners, 35 sequential-CPU-time of ~1850s caps wall clock around 8 min
even at concurrency=4. Shard the suite across 3 GHA runners via matrix
strategy. The runner now reads PASEO_CLI_TEST_SHARD/SHARD_TOTAL and
distributes files into buckets — known long-pole tests
(05/06/11/13/14-...) round-robin first so they spread across shards
instead of clustering by their numeric prefixes, then the remainder
fills in the reverse direction to balance light load.

Local run is unchanged (single shard by default). Expected per-shard
wall on CI: ~2:30 + setup ≈ ~4:30 total.
2026-05-05 19:58:55 +07:00
Mohamed Boudra 75247efbd5 refactor(agent-providers): fix type-aware lint errors in diagnostic-utils and generic-acp-agent (#705)
* refactor(agent-providers): add type guards and fix type-aware lint errors in diagnostic-utils, generic-acp-agent, and tool-call-detail-primitives

* fix(server): defer PTY onExit to allow pending data events to fire

On Linux, node-pty's onExit callback can arrive before the last buffered
PTY data chunk is delivered via onData. Wrapping finish() in setImmediate
gives libuv's I/O poll phase a chance to flush remaining PTY reads before
the promise resolves, preventing tail bytes from being silently dropped.

Fixes a flaky worktree-bootstrap test that reliably reproduced on Linux CI.

* unslop: remove dead guard, fix import order, trim comment

- generic-acp-agent: remove isNonEmptyStringArray and its guard; the
  constructor parameter is already typed [string, ...string[]] so the
  check can never fire
- provider-registry: move isNonEmptyStringArray below the import block
  instead of between two import groups
- worktree: condense 3-line comment to one line per project convention
2026-05-05 19:58:55 +07:00
Mohamed Boudra 660b4d3cec refactor(app): fix type-aware lint errors in voice, tabs store, host-connection, audio recorder (#706)
Clear all type-aware lint errors in four app state/runtime files:

- voice-context.tsx: bind runtime methods before passing to useSyncExternalStore
  and object spreads to satisfy the unbound-method rule
- workspace-tabs-store.ts: replace unsafe `as` casts with isPlainRecord type
  predicate + toObjectRecord; add coerceWorkspaceTabTarget to bridge unknown
  storage data to WorkspaceTabTarget without assertions
- host-connection.ts: same isPlainRecord/toObjectRecord pattern; replace
  String(record.x ?? "") calls with typeof guards to fix no-base-to-string
- use-audio-recorder.native.ts: construct real Blob instead of casting an
  object literal; restructure useEffect for consistent-return; drop await on
  void recorder.record(); use instanceof Error for message extraction; remove
  redundant Boolean() wrapping
2026-05-05 19:58:16 +07:00
Mohamed Boudra c8274ba88a refactor(claude-agent): replace unsafe type assertions with type guards (#707)
Adds isObjectRecord, isUnknownArray, isChildProcessWithStreams, and
isImageMimeType type predicates to eliminate all no-unsafe-type-assertion
violations surfaced by typeAware lint mode. Fixes floating promise, adds
throw after exhaustive switch, and widens readCompactionMetadata to accept
unknown so callers need no casts.
2026-05-05 19:58:16 +07:00
Mohamed Boudra 8b54d27cbc refactor(server): add getErrorMessage helper and fix error-related type-aware lint errors (#704)
* refactor(server): add getErrorMessage helper and fix error-related type-aware lint errors in session.ts

* fix build: correct parseClientCapabilities type handling
2026-05-05 19:57:35 +07:00
Mohamed Boudra d359bffed5 refactor(agent-providers): add toObjectRecord helper and fix type-aware lint errors in codex and claude agents (#699) 2026-05-05 19:57:35 +07:00
Mohamed Boudra b2c88e4312 refactor(speech): add ONNX type augmentation and fix type-aware lint errors (#701) 2026-05-05 19:56:52 +07:00
Mohamed Boudra ab9f07dd8a fix(app): make e2e setup an auto fixture so first-of-spec tests get setup (#702)
* fix(app): make e2e setup an auto fixture so it runs for the first test of every spec

The fixtures.ts beforeEach was declared at the top level of a non-test
fixture file. Playwright sometimes skipped it for the first test of a
subsequent spec when multiple specs ran in the same worker — that test
hit page.evaluate without the seed nonce or daemon registry in
localStorage and failed (then passed on retry, masking the bug behind
retries: 1). Reproduced locally by running sidebar-workspace then
startup-loading: the first startup-loading test got no fixture setup
and threw "Expected e2e seed nonce".

Move the setup into an `auto: true` fixture, the canonical Playwright
pattern for running setup for every test in a workspace. The afterEach
console-attachment is folded into the same fixture's teardown.

* refactor(server): simplify nullish handling in workspace-git-metadata

Drop the explicit `null` arg in `deriveProjectSlug(input.cwd, null)` —
the second parameter already defaults to `null`. Inline the
`repoName && repoName.length > 0` check in `parseGitHubRepoNameFromRemote`
since `pop()` on a non-empty array returns a non-empty string here, and
`|| null` covers the empty-string case directly.
2026-05-05 19:56:52 +07:00
Mohamed Boudra f974812dfc refactor(relay): fix type-aware lint errors in WebSocket and crypto handling (#698) 2026-05-05 19:56:52 +07:00
Mohamed Boudra 400934f19c schedule: add paseo schedule update to edit schedules in place (#694)
* schedule: add `paseo schedule update` to edit schedules in place

Editing a schedule today requires delete+recreate, losing run history
and the schedule id. This adds an additive RPC and CLI command that
patches name, prompt, cadence, new-agent target fields, max-runs, and
expires-in without touching runs or in-flight executions. nextRunAt is
recomputed only when the cadence actually changes.

* schedule(cli): share cadence flag parser between create and update

Both paths were turning --every/--cron into a ScheduleCadence with
near-identical code. Extract `parseCadenceFromFlags` so the literals
and the exclusivity check live in one place; create wraps it to
require a value, update lets it stay optional.
2026-05-05 19:56:52 +07:00
Mohamed Boudra 82cf11aaae fix(server): derive non-GitHub project display names from remote owner/repo (#697)
Reconciliation overwrote correctly-set project display names with the
directory name for non-GitHub remotes (e.g. gitlab.com/acme/app), because
buildWorkspaceGitMetadataFromSnapshot only handled GitHub URLs while the
registry-model layer used the more general deriveProjectGroupingKey path.
Reuse that path here so both layers agree on the owner/repo display name.
2026-05-05 19:56:52 +07:00
Mohamed Boudra 3bf8d483d3 refactor(app): remove unnecessary String() and Boolean() conversions from type-aware lint fixes (#696) 2026-05-05 19:56:52 +07:00
Mohamed Boudra 84d822450e refactor(server): remove unnecessary String() conversions from type-aware lint fixes (#695) 2026-05-05 19:56:52 +07:00
Mohamed Boudra cccccca18e refactor(server): remove redundant null from unknown union types (#693) 2026-05-05 19:56:52 +07:00
Mohamed Boudra 936deaa869 refactor(app): remove redundant type constituents from type definitions (#692) 2026-05-05 19:56:52 +07:00
Mohamed Boudra 946152d820 refactor(server): replace JSON.parse type assertions with Zod validation (#691)
Replace unsafe 'JSON.parse(content) as Type' patterns with proper Zod schema
validation. This fixes type-aware lint errors and provides runtime safety.

- pid-lock.ts: Add pidLockInfoSchema and parsePidLockInfo helper
- package-version.ts: Add packageJsonSchema and parsePackageJson helper
- relay-transport.ts: Add isRecord type guard to avoid unsafe type assertion
2026-05-05 19:56:51 +07:00
Mohamed Boudra 2b6d7d4ec2 schedule: fire --every now by default, add run-once for cron-style triggers (#689)
Interval schedules used to wait the full interval before their first run, which
made `--every 1d` feel broken for fresh schedules. Now `--every` fires
immediately on creation; `--cron` keeps waiting for the next slot. `--no-run-now`
and `--run-now` override the defaults, and the parser rejects redundant combos.

Adds `paseo schedule run-once <id>` to manually trigger a single run without
advancing cadence or recomputing completion. The new `runOnCreate` field and
`schedule/run-once` RPC are additive on the WebSocket schema.
2026-05-05 19:56:51 +07:00
Mohamed Boudra f11aea3223 mcp(create_agent): validate mode and refuse silent cross-provider inheritance (#688)
The MCP create_agent tool inherited the parent agent's mode regardless of
provider, so a Claude parent in bypassPermissions spawning an opencode
child would feed an invalid mode to opencode and the new agent would die
in error state. The fix:

- Add an optional mode field to the agent-to-agent input schema.
- Validate any explicit mode against the target provider's available
  modes; throw with the list when invalid.
- Inherit the caller's mode only when both sides use the same provider;
  otherwise refuse with a helpful error listing the target's modes.
2026-05-05 19:56:51 +07:00
Mohamed Boudra 2b75df6132 refactor(relay): remove unnecessary awaits from synchronous crypto functions (#687) 2026-05-05 19:56:51 +07:00
Mohamed Boudra b45f0a9ad1 feat(cli): paseo worktree create with MCP parity (#686)
Mirrors the MCP create_worktree tool's three modes (branch-off,
checkout-branch, checkout-pr) against the daemon's existing
createPaseoWorktree RPC, so CLI users (especially over --host) can
provision worktrees in the paseo-managed location.
2026-05-05 19:56:51 +07:00
Mohamed Boudra 4b260eb516 fix(cli): update schedule provider/mode error message substring in test
The error message gained a `--mode` mention when the schedule mode flag
landed; the existing CLI integration test still asserted on the old
exact-prefix substring and broke main CI for all PR builds.
2026-05-05 19:56:51 +07:00
Mohamed Boudra 14c33aad0b cli(schedule): require --cwd when --host is set (#685)
process.cwd() is the local path and won't exist on a remote daemon, so
fail fast client-side instead of running the schedule in a wrong dir.
2026-05-05 19:56:51 +07:00
Mohamed Boudra e22b497a08 voice: quieter thinking tone, log cleanup, and small ui polish
- Add scripts/lower-thinking-tone.mjs to scale the thinking-tone PCM
  amplitude in-place; apply it at 0.1 so the cue is a soft indicator
  instead of triggering the VAD via mic feedback.
- Drop the "Received first voice_audio_chunk" log that re-fires every
  summary window because the chunk counter is reset.
- Match Spoke message icon and label sizing to the standard tool-call
  badge.
- Append a spoken-input instruction so voice replies route through the
  speak tool.
2026-05-05 19:56:51 +07:00
Mohamed Boudra 91865ba66e Switch voice turn controller to streaming transcription 2026-05-05 19:56:51 +07:00
Mohamed Boudra 4d31cd4013 fix(opencode): forward provider retries instead of swallowing them
OpenCode subproviders (e.g. opencode/kimi-k2.6 on OpenCode Zen) emit
session.status:retry events with messages like "Internal server error"
when the upstream provider returns 5xx. opencode itself retries
indefinitely with backoff and never emits a terminal event for these.

Previously the adapter only surfaced retry messages on a small allowlist
of "fatal" tokens (insufficient balance, invalid api key, etc.) and
silently dropped everything else. The agent appeared hung from the
user's perspective — no message, no spinner update, nothing — until the
upstream eventually recovered or the user manually interrupted.

Forward every session.status:retry as a non-terminal timeline error
item so the user can see what opencode is doing, mirroring opencode's
own TUI. Drop the fatal-token allowlist: classifying which retries are
"really" terminal is opencode's job, and synthesizing turn_failed for
ones we guess at is misleading anyway because opencode keeps spending
upstream while we tell the user the agent is done.

Also a small design pass on the timeline error rendering:
- drop the redundant "Agent error" prefix (the message is descriptive)
- drop the colored box background (visual weight too high for a retry)
- align the icon vertically to the first text line (height+center)
- make the message text selectable so users can copy errors
2026-05-05 19:56:51 +07:00
Mohamed Boudra 0775f59a6f Add --mode to schedule and loop CLI, default background runs to unattended mode
Plumb --mode/--verify-mode through paseo schedule create and paseo loop run.
Mark each provider's unattended mode (claude bypassPermissions, codex/opencode
full-access, copilot autopilot) so loop and schedule services pick it by
default when no explicit modeId is given.
2026-05-05 19:56:26 +07:00
Mohamed Boudra 5feaa7a101 Type CLI command host/json options at the source
The CommandOptions interface in packages/cli/src/output/with-output.ts had
an open `[key: string]: unknown` indexer, so every consumer of the global
--host and --json options had to cast `options.host as string | undefined`
at the call site. Add `host?: string` and `json?: boolean` to the interface
and remove 29 redundant casts across 12 command files.
2026-05-05 19:56:26 +07:00
Mohamed Boudra 4cd9e76bd2 Remove unnecessary type assertions across codebase
Add oxlint-tsgolint and configure typescript/no-unnecessary-type-assertion
to flag redundant `!` and `as Foo` casts. Type-aware mode is left off by
default to keep `npm run lint` fast; the rule sits configured for when we
turn type-aware on intentionally. Auto-fix removed ~283 redundant casts;
two manual touch-ups: a real tsgolint false positive in split-container.tsx
and a stale ChildProcess import after a double-cast collapsed.
2026-05-05 19:56:26 +07:00
Mohamed Boudra 78fe3e4df3 Drop subagent task notifications from parent timeline
Subagent task_notification system messages arrive without
parent_tool_use_id but with tool_use_id pointing at the parent's Task
call, so they slip past the sidechain router and render as top-level
"Task Notification" rows in the parent's timeline. Skip them when the
referenced tool_use is a Task call; parent-level background bash
notifications still flow through.
2026-05-05 19:56:26 +07:00
Mohamed Boudra 72e7c7e1ed Replace fictional fastlane action with Spaceship build-processing poll
The Fastfile called wait_for_build_processing_to_be_complete, which
isn't a built-in fastlane action and isn't published as a plugin
anywhere on rubygems. The submit_review lane has therefore failed
on every release that reached it (v0.1.65-beta.1, v0.1.66, v0.1.67).

Replace it with a direct Spaceship::ConnectAPI poll: fetch the build
matching the latest TestFlight build number, wait until its
processing_state is VALID, then hand off to deliver. 30-minute cap
with a clear failure message on INVALID/FAILED or timeout. Spaceship
ships with fastlane so no plugin or extra gem is required.

Lands in the next release; v0.1.67 needs a manual review submission
from App Store Connect.
2026-05-05 19:56:26 +07:00
Mohamed Boudra 1e5e17f000 chore(release): cut 0.1.69 2026-05-05 19:40:12 +07:00
Mohamed Boudra 20de118373 Add changelog for 0.1.69 2026-05-05 19:39:18 +07:00
Mohamed Boudra fd4e26ca9b Align script TypeScript lib with server build 2026-05-05 18:54:29 +07:00
Mohamed Boudra ca3e55813e Keep daemon worker supervision explicit 2026-05-05 18:48:07 +07:00
Mohamed Boudra 3fad128d02 Restart daemon worker crashes in production 2026-05-05 18:42:21 +07:00
Mohamed Boudra 0cb9da17cd Daemon hardening epic 2026-05-05 18:21:10 +07:00
Mohamed Boudra 84478a2dba chore(release): cut 0.1.68 2026-05-05 16:46:10 +07:00
Mohamed Boudra 93065b20f7 Add changelog for 0.1.68 2026-05-05 16:45:16 +07:00
Mohamed Boudra bb8762e122 Fix desktop settings first-launch race 2026-05-05 16:43:38 +07:00
Mohamed Boudra 15a2e3bdcb chore(release): cut 0.1.67 2026-05-04 01:43:24 +07:00
Mohamed Boudra 64ba05cea5 Add v0.1.67 changelog entry 2026-05-04 01:42:23 +07:00
Mohamed Boudra 1521ceb381 Surface desktop daemon gate failures instead of silent no-op
The async settings gate added in f0d96f8e called
shouldStartDaemon() inside Promise.resolve(...).then(...) with no
catch. If loadDesktopSettings() rejects (corrupted JSON, FS error),
the daemon never starts, no error renders on the splash, and the
retry button repeats the same silent path.

Add a recordError method to DaemonStartService and an onGateError
callback to startDaemonIfGateAllows / startHostRuntimeBootstrap.
_layout.tsx wires it through so a gate rejection populates
lastError, the splash shows the failure, and retry has signal.
2026-05-04 01:40:47 +07:00
Mohamed Boudra 4338f5b46c Fix workspace reconnect playwright tests after toast move
Test #1 was asserting agent-reconnecting-toast on a workspace with no
agents — but commit 1daa1314 moved the reconnect indicator from the
workspace banner into the per-agent panel toast. Create an idle agent
and navigate to it so the agent panel mounts before dropping the
daemon gate.

Test #2 regex still pinned the old "Connecting to localhost" copy;
commit c534c857 tightened it to just "Connecting" with the hostname in
the description. Match the new title plus the existing offline copies.
2026-05-04 01:18:37 +07:00
Mohamed Boudra e8a64fb569 ci: build server before desktop tests
f0d96f8e added packages/desktop/src/daemon/daemon-manager.test.ts,
which calls vi.mock("@getpaseo/server", ...). Vite's module
resolution still needs to find the package's main entry, so
desktop CI must build the server (and its dependency chain) before
running the tests. Mirrors the prebuild steps used by typecheck,
server-tests, and playwright.
2026-05-04 00:40:38 +07:00
Mohamed Boudra cf1f849b68 Update MCP create_agent test to match async branch auto-name
7c85341a moved first-agent branch auto-naming out of the worktree
service (sync slugify) into the workflow layer (async LLM call).
The MCP test stubs createPaseoWorktree, bypassing the workflow,
so the placeholder mnemonic branch is never renamed at this layer.
Replace the obsolete sync-slugify outcome assertion with a
placeholder-presence check; the auto-name logic itself is covered
in worktree-branch-name-generator.test.ts.
2026-05-04 00:31:33 +07:00
Mohamed Boudra bc0886ad7c Merge branch 'main' of github.com:getpaseo/paseo 2026-05-04 00:16:08 +07:00
Mohamed Boudra 12fcfe53eb Make structured response generation ephemeral end-to-end
Plumbs persistSession through the structured response pipeline so
metadata, branch name, commit message, and PR text generators no
longer leave provider-side artifacts behind:

- Codex: passes ephemeral: true on thread/start (no rollout file)
- OpenCode: deletes the session via session.delete on close
- Claude: forwards persistSession: false to the SDK query

Adds a real-credentials e2e test per provider that asserts the
generated title is applied AND no persistence artifact is produced
(rollout for Codex, project JSONL for Claude, leftover session for
OpenCode).
2026-05-04 00:10:50 +07:00
Mohamed Boudra 7c85341a42 Fix worktree creation and archive flow
Server: drop the synchronous branch-name generator dep, use the
worktree slug as the initial branch, and move first-agent branch
auto-naming to an async post-creation step backed by a structured
LLM call. Guards against renaming when the placeholder branch has
already been changed.

App: make workspace and worktree archive optimistic, rolling back
the local hide if the daemon call fails, and suppress incoming
workspace upserts while an archive is pending.
2026-05-03 23:22:54 +07:00
Mohamed Boudra c534c857a4 Tighten workspace host connecting copy 2026-05-03 23:01:29 +07:00
Mohamed Boudra 6d8c7c4d2d Fix desktop settings legacy override 2026-05-03 22:57:33 +07:00
Mohamed Boudra f0d96f8e5a Fix built-in daemon management toggle 2026-05-03 22:02:40 +07:00
Mohamed Boudra f8d4758e6b Run iOS Fastlane review-submit on macOS
Linux EAS runners don't ship Ruby/Bundler, so `bundle install`
fails with "bundle: command not found". macOS workflow runners
have Ruby 3.2 + Fastlane preinstalled, so switching this job to
runs_on: macos-medium gets us there without a manual install step.
2026-05-03 21:27:24 +07:00
Mohamed Boudra 221b6665a0 chore(release): cut 0.1.66 2026-05-03 20:48:53 +07:00
Mohamed Boudra 94dd36a4c9 Fix EAS Fastlane working_directory doubling
The eas/checkout step already cd's into packages/app (where eas.json
lives), so the explicit `working_directory: ./packages/app` on the
Fastlane steps resolved to /home/expo/workingdir/build/packages/app/packages/app
and failed every release with ENOENT.
2026-05-03 20:44:01 +07:00
Mohamed Boudra 84c1ff560f Add 0.1.66 changelog entry 2026-05-03 20:39:26 +07:00
Mohamed Boudra b7f9092e93 Fix terminal renderer remount loading 2026-05-03 20:38:12 +07:00
Mohamed Boudra ade05607d2 fix(app): latch startup store readiness 2026-05-03 20:15:19 +07:00
Mohamed Boudra 6d13796b2d Move workspace gate background and root layout off useUnistyles
The workspace gate (loading/unreachable/missing) used surfaceWorkspace,
which clashed with the panels' surface0. Switch the gate shell to
surface0 so it matches the agent panel.

Also remove three hot-path useUnistyles() calls from _layout.tsx that
were re-rendering the whole app on every theme/breakpoint/insets change:
RootLayout and AppContainer move to StyleSheet.create, and the desktop
window-controls effect lifts into a small leaf component.
2026-05-03 19:49:10 +07:00
Mohamed Boudra 191cea47a0 Merge branch 'main' of github.com:getpaseo/paseo 2026-05-03 19:25:23 +07:00
Mohamed Boudra 0aa4868b31 Fix terminal DSR replies 2026-05-03 19:24:30 +07:00
Mohamed Boudra 4332eca9ca Shorten agent initialization timeout 2026-05-03 19:12:36 +07:00
Mohamed Boudra fc31d31493 Disable dev client runtime metrics logging 2026-05-03 19:11:25 +07:00
Mohamed Boudra 8ba71cc189 Preserve live markdown block newlines 2026-05-03 19:09:24 +07:00
Mohamed Boudra 38c1b08433 chore(release): cut 0.1.65 2026-05-03 17:20:28 +07:00
Mohamed Boudra 21a5d4f061 Promote 0.1.65 changelog heading to stable 2026-05-03 17:19:34 +07:00
Mohamed Boudra 1daa131480 Replace workspace reconnect banner with persistent agent panel toast
The workspace reconnect banner ignored safe-area insets on Android,
overlapping the system status bar. The agent panel already shows a
"Reconnecting..." toast on disconnect, so consolidate on that and drop
the banner entirely. Add persistent toast support (durationMs: null)
and dismiss the toast when the connection returns to online instead of
auto-dismissing after 2.2s.
2026-05-03 17:17:02 +07:00
Mohamed Boudra f33a5191df Drop obsolete Connecting… assertion from reconnect welcome DSL
The 'Connecting…' placeholder was removed from welcome-screen.tsx in
02adadbb (Always show welcome copy on welcome screen) but the e2e
helper still asserted it visible, breaking startup-loading.spec.ts.
2026-05-03 15:42:57 +07:00
Mohamed Boudra d6c3896fd9 Update test mocks for new serviceUrlBehavior setting
f58cfe9 (Open script service URLs in-app or external) added
serviceUrlBehavior to AppSettings and a new useDropdownMenuClose
export from dropdown-menu. The unit tests were not updated:

- use-settings.test.ts: expected settings objects missed the new
  serviceUrlBehavior field.
- workspace-scripts-button.test.tsx: dropdown-menu mock missed
  useDropdownMenuClose, breaking HostLinkRow render.
2026-05-03 15:38:01 +07:00
Mohamed Boudra f2da4b861b Fix sidebar workspace list test AsyncStorage mock
fa20f313 wired AsyncStorage persistence into
activateNavigationWorkspaceSelection. The mock here returned undefined
from setItem, so the .catch() in persistLastWorkspaceRouteSelection
threw. Make get/set/removeItem return resolved promises like real
AsyncStorage.
2026-05-03 15:25:04 +07:00
Mohamed Boudra eec9804567 Tighten 0.1.65-beta.5 changelog and document unreleased-fix trap 2026-05-03 15:20:35 +07:00
Mohamed Boudra f58cfe9008 Open script service URLs in-app or external
Adds a Service URLs setting (ask / in-Paseo / external browser) that
controls where URLs from running scripts open on desktop. First click
prompts with a "don't ask again" checkbox; in-Paseo opens a workspace
browser tab. Closing a browser tab now clears its session partition.
2026-05-03 15:14:28 +07:00
Mohamed Boudra 02adadbbc8 Always show welcome copy on welcome screen
Drop the "Connecting…" placeholder shown while reconnecting to saved
hosts. The screen now keeps the welcome copy and add-host actions
visible until the auto-redirect to an online host fires.
2026-05-03 15:05:59 +07:00
Mohamed Boudra 086bc2beee Fix desktop release build args 2026-05-03 15:03:32 +07:00
Mohamed Boudra 831d0bbf6e Hide element picker in production 2026-05-03 14:36:01 +07:00
Mohamed Boudra d4fa12c3f6 fix(desktop): centralize desktop build script 2026-05-03 14:35:20 +07:00
Mohamed Boudra f993b1d856 Dismiss keyboard when opening mobile sidebar 2026-05-03 14:17:15 +07:00
Mohamed Boudra 2faacc59f1 chore(release): cut 0.1.65-beta.5 2026-05-03 13:58:46 +07:00
Mohamed Boudra 65cfe4bda4 Reduce agent timeline focus catch-up 2026-05-03 13:57:48 +07:00
Mohamed Boudra fa20f313d3 Simplify workspace reconnect gating 2026-05-03 13:50:20 +07:00
Mohamed Boudra b2247450f9 Fix terminal snapshot flushing 2026-05-03 13:25:19 +07:00
Mohamed Boudra d89ecae615 fix(server): clean up OpenCode process trees
Spawn the shared OpenCode server in its own POSIX process group and terminate provider child process trees with graceful timeout escalation before forcing SIGKILL. Reuse the same helper for Codex app-server cleanup so process-tree behavior is covered consistently across providers.

Add cross-platform unit coverage for macOS/Linux process groups, Windows taskkill cleanup, and timeout escalation. Add the process-tree test to the Windows-critical CI allowlist; Linux full server tests already include it.

Refs #227
2026-05-02 21:44:59 +07:00
Mohamed Boudra d06e3e9494 chore(release): cut 0.1.65-beta.4 2026-05-02 20:41:37 +07:00
Mohamed Boudra b7802ae271 chore(release): prep 0.1.65-beta.4 changelog
Update CHANGELOG.md in place per beta policy and add a compat note on the
`sub_agent.actions` field flagging it as drop-on-cleanup once clients
<= 0.1.65-beta.3 are out of the field.
2026-05-02 20:40:41 +07:00
Mohamed Boudra d53d601043 refactor(server): inline client capability parsing
With capability negotiation in place, the consumer-side tolerance pattern is unnecessary. Drop the dead readDeclaredClientCapabilities helper, inline the parsing in ClientCapabilities.fromHello, delete a tautological assertion in the relay reconnect test, and document the compatibility rules in architecture.md.
2026-05-02 20:30:25 +07:00
Mohamed Boudra ca318f29cf feat(client): advertise reasoning merge capability 2026-05-02 20:30:25 +07:00