46 Commits
Author SHA1 Message Date
Mohamed Boudra 772ff8d6f3 fix(desktop): preserve Linux sandboxing wherever the host allows it (#4447)
* fix(desktop): preserve Linux sandboxing wherever the host allows it

Chromium checks its Linux sandbox before main.js, while package installation probes run as root and miss AppArmor restrictions on desktop users. Choose the launch flags before exec and always install the SUID alternative for native packages. Test published artifacts as an ordinary user with namespaces both denied and allowed; never repair permissions in the smoke harness.

* fix(desktop): retain the Linux release build baseline

* fix(ci): allow canceled desktop smoke uploads to stop

* test(desktop): verify the installed RPM sandbox under AppArmor

* fix(ci): resolve packaged desktop dependencies before installation

* chore(desktop): keep QA evidence out of the repository
2026-09-11 09:05:26 +02:00
Mohamed Boudra 94fc4e5d49 docs(release): document temporary next and hotfix branches (#4651) 2026-09-10 11:10:21 +02:00
Mohamed Boudra 509a3e17bd feat(app): read the changelog in the app instead of the browser (#4576)
What's new opens an adaptive sheet — bottom sheet on compact, centred card on
desktop — that fetches CHANGELOG.md from the repository and renders it with the
app's own chrome. The desktop update callout, the sidebar help menu, and a new
row in Settings → About all open it; the sheet header links out to
paseo.sh/changelog.

The parser commits to two facts only: `##` starts a release and `###` starts a
section. Section titles are read from the document rather than matched against a
list, and everything under a section passes through verbatim to the Markdown
renderer, so a future callout, block quote, code fence or image needs no parser
change. Fences are tracked because a fenced sample is the one thing that can
fool a line scan.

The document is fetched rather than bundled because the app has to describe a
release that shipped after it was built, which is the update callout's whole
purpose. It goes straight to the repository rather than through a host: the
notes describe the app, and routing them through a daemon would make them
depend on which host happens to be connected. Nothing is fetched or parsed
until the sheet opens.

The latest release renders as soon as there is one and the rest of the first
page follows in a transition, so React slices that work around the opening
animation instead of committing hundreds of list items at once.
2026-09-09 15:23:01 +02:00
Mohamed Boudra 9e90b86afa Restore reliable macOS desktop updates (#4322)
* fix(desktop): restore macOS app updates

Electron 41's Squirrel helper can leave the update handoff dormant on current macOS, so Paseo quits cleanly but relaunches the old bundle. Electron 44 wakes ShipIt through its XPC service.

Include updater lifecycle events and ShipIt state in app diagnostics so future handoff failures identify the current version, target version, cache paths, and installer output.

* fix(desktop): harden updater diagnostics

Keep each ShipIt file's evidence available when another read fails, carry the service-selected version into updater lifecycle logs, and make clean workspace installs resolve the Electron runtime used by desktop tests.

* refactor(desktop): name updater install options

* refactor(desktop): name updater log payloads

* refactor(desktop): name clipboard payload

* fix(desktop): surface updater lookup failures

* test(desktop): await guest focus transition

* fix(desktop): guard macOS update compatibility

* test(release): validate desktop manifests before publish

* test(desktop): await populated daemon pid file
2026-09-04 22:17: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
Anton LazarevandMohamed Boudra f6288629ff Fastlane metadata format for F-Droid releases (#2501)
* add f-droid metadata support

* share version code calculation with website

* preserve blockquoted sections in changelogs

* refactor(android): simplify stable F-Droid metadata

Generate store changelogs only for stable releases and keep native version-code ownership in the existing release module.

* test(android): run F-Droid changelog suite in CI

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-25 23:37:54 +02:00
Mohamed Boudra 929d2b717e fix(plugins): publish the plugin SDK under the @getpaseo scope
The daemon imports the plugin SDK at runtime, but the workspace was named
@paseo/plugin and marked private, so it was never published. 0.5.0-beta.1
shipped @getpaseo/server depending on a package that does not exist and
`npm install @getpaseo/cli@beta` failed with a 404 for every user.

Two things hid it. sync-workspace-versions only rewrites deps matching
@getpaseo/*, so the "*" range on @paseo/plugin survived untouched into the
published tarball. And `npm pack --dry-run`, which is all release:check and
CI run, lists files without ever resolving the dependency graph.

Renaming to @getpaseo/plugin rather than publishing the old name: @paseo is
not our scope on npm, so that name could never have been published at all.
The rename also brings the package under the version-sync filter, which is
what pins it correctly from here on.

Plugins scaffolded against the old name still import @paseo/plugin. Both
spellings resolve through plugin-sdk-specifiers.ts, tagged COMPAT with a
removal date, so existing plugins keep loading.

This does not repair 0.5.0-beta.1 — a published tarball's dependencies
cannot be changed. The package publishes with the next release.
2026-08-19 15:52:51 +02:00
Mohamed Boudra 4149eeb407 docs(release): make changelog wording factual 2026-08-13 21:26:48 +02:00
Mohamed Boudra 9c91dbbf42 docs(release): require PR context for changelogs 2026-08-13 20:01:08 +02:00
Mohamed Boudra 7ac4303d8f docs(release): streamline release workflow
Make the release document the single source of truth. ACP drift is explicit opt-in, release preparation uses one remote batch, and a heartbeat owns completion through published artifacts and store submissions. Preserve one changelog entry per beta and collapse the series on promotion.
2026-08-08 13:49:22 +02:00
Mohamed Boudra 1c43e4eea1 feat(website): offer the beta channel on the download page
Beta testers had to find prerelease assets on GitHub by hand. The
download page now carries a Stable/Beta switch, with stable staying the
default and the canonical URL.

The channel lives in the URL (?channel=beta) rather than client state so
maintainers can link someone straight to it. That link outlives the beta
it was shared for, so the switch only renders while the newest
prerelease leads stable on its core version, and a stale ?channel=beta
falls back to stable instead of serving a promoted version twice.

"What's new" deep-links the minor group anchor (/changelog#release-0.3),
not the exact entry: promotion rewrites the -beta.N entry in place, so
that anchor dies while the group survives — and the group is the
stable-to-beta diff a beta downloader came to read. A version missing
from the bundled changelog links plain /changelog rather than a dead
anchor, which covers the window between a tag going public and the site
redeploying.

Homebrew, the app stores, and the web app have no beta, so the Beta view
drops those rows instead of showing inert placeholders.
2026-08-05 16:39:59 +02:00
Mohamed Boudra d191fa6685 feat(app): automate iOS beta distribution
Beta tags now reach external testers without per-release dashboard work. Reserve distinct native build slots so successive betas and the promoted stable build can coexist under one app version.
2026-08-04 19:21:22 +02:00
Mohamed Boudra acb8506d1f Revert the timeline optimistic and pagination rework (#2596)
* Add npm release track invariant and beta dist-tag procedure

* Revert "Keep older chat history and image previews stable (#2490)"

The timeline optimistic/pagination rework needs more work than main releases can wait for. Reverted together with #2484; both are reapplied on integration/timeline-optimistic-rework.

* Revert "Stop completed turns from appearing stuck (#2484)"

See the #2490 revert. #2490 built on this submission-authority change, so the two revert and reapply as a pair.
2026-07-29 13:35:43 +02:00
Mohamed Boudra fe28850fad docs(relay): point readers to the official service
Remove the maintainer callout and star history chart from the README while keeping translated copies aligned.
2026-07-26 20:47:25 +02:00
Mohamed Boudra df2b7cab46 Document release version classification 2026-07-17 15:07:08 +02:00
Mohamed Boudra 70472dc945 Always install the newest eligible desktop update (#2149)
* 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
2026-07-17 10:06:32 +02:00
Mohamed Boudra 623c05aa4d Revert "Always revalidate desktop updates before install"
This reverts commit 7d80fdfd12.
2026-07-16 21:20:57 +02:00
Mohamed Boudra 7d80fdfd12 Always revalidate desktop updates before install 2026-07-16 20:17:58 +02:00
Mohamed BoudraandAnton Lazarev b6d49da4df Support F-Droid Android builds (#1768)
* fix(android): support source-based APK builds

Co-authored-by: Anton Lazarev <22821309+antonok-edm@users.noreply.github.com>

* fix(android): address fdroid review feedback

Co-authored-by: Anton Lazarev <22821309+antonok-edm@users.noreply.github.com>

* fix(android): complete the F-Droid build profile

* fix(app): isolate the F-Droid runtime flag

---------

Co-authored-by: Anton Lazarev <22821309+antonok-edm@users.noreply.github.com>
2026-07-13 17:18:19 +08:00
Mohamed Boudra d28e174b38 ops(relay): require manual deployment 2026-07-12 00:09:15 +02:00
Mohamed Boudra f226222638 Build Docker images from source (#1877)
* fix(docker): build images from source

Collapse the npm-install and source-build image paths into one Dockerfile so every Docker image is built from the checked-out workspace packages. Include procps in the runtime image because provider process cleanup depends on ps through tree-kill on Linux.

* fix(docker): include native speech packages

* fix(docker): cover source build inputs

* fix(docker): ignore local agent artifacts
2026-07-03 15:49:23 +02:00
Mohamed Boudra 276c1f48f1 ci: add Docker-only publish dispatch [skip ci] 2026-06-27 09:49:20 +00:00
Mohamed Boudra 62bdb52eaa ci: build beta Docker images from source 2026-06-27 05:17:51 +00:00
Mohamed BoudraandHerbrant 2c9db5279c Run Paseo from an official Docker image (#1740)
* Add Docker images and agent Docker Mods

Ship official container images that run the Paseo daemon headless. One
Dockerfile parametrized by BASE_IMAGE covers Debian 12/13, Ubuntu 22.04/24.04
and Alpine; it bundles Node 22, the npm-published server + CLI, a vendored
s6-overlay as PID 1, and a small Docker Mods loader.

Agents are chosen at runtime via DOCKER_MODS (pipe-separated mod images). Each
mod is a FROM scratch image carrying only an install hook that runs
`npm install -g <agent-cli>`; the loader pulls the layers from the registry,
extracts them, and runs the hook before the daemon starts, so any requested
agent is on PATH when Paseo probes provider availability.

- docker/base: Dockerfile, install scripts, s6 services, mods loader
- docker/mods/*: claude-code, codex, copilot, opencode, pi
- docker/docker-compose.example.yml + docker/README.md
- .github/workflows/docker.yml: multi-arch (amd64/arm64) buildx matrix,
  publishes to ghcr.io/getpaseo on version tags
- docs/docker.md + CLAUDE.md docs index row

* feat(docker): print pairing QR and link on daemon startup

Add an s6 oneshot service that waits for the daemon to listen, then runs
`paseo daemon pair` so the pairing QR code and link surface in the container
logs. Best-effort: never blocks boot, skips gracefully when relay is disabled.
Opt out with PASEO_PAIRING_QR=0.

* build(docker): add Arch image support

* ci(docker): build Arch without Buildx

* docs(docker): document paseo env contract

* feat(docker): add opt-in sudo mode

* docs(docker): link env references

* fix(docker): create agent config dirs

* fix(docker): default home to /home/paseo

* docs(docker): document agent auth setup

* docs(docker): document relay port setup

* fix(docker): install Node from tarball

* docs: add Docker quick start

* docs(docker): remove legacy home example

* docs(docker): set container hostname

* fix(docker): prepare opencode storage

* fix(docker): allow paseo login shell

* fix docker opencode permissions

* ci(docker): use Node 24 actions

* fix(docker): install bzip2 runtime tools

* fix(docker): update Pi mod package

* fix(docker): quiet default daemon logs

* fix(docker): split home from state

Docker images now keep HOME at /home/paseo and store Paseo daemon state under /home/paseo/.paseo by default.

Existing volumes can keep the old layout by setting PASEO_HOME=/home/paseo.

* fix(docker): keep mods out of paseo home

* ci(docker): skip alpine arm64 builds

* fix(docker): address review findings

* fix(docker): verify s6 overlay downloads

* fix(docker): honor custom healthcheck port

* fix(docker): fail on mod extraction errors

* feat(docker): add official container image

Ship a focused daemon image with the bundled web UI enabled and document extending it with agent CLIs.

* ci(docker): publish images only on stable releases

* fix(docker): check daemon health over HTTP

---------

Co-authored-by: Herbrant <cdavide98carnemolla@gmail.com>
2026-06-26 14:48:13 +08:00
Mohamed Boudra ecf4f9037e docs(release): document release previews 2026-06-25 12:14:15 +07:00
Mohamed Boudra 90d386b88e Restore changelog entries for betas (#1568)
* Restore changelog entries for betas

Beta users check release notes, so each beta now updates an in-place
CHANGELOG.md entry that promotion overwrites with the final stable entry
— no -beta.N heading is left behind. The release machinery already
parses beta headings and syncs them; this restores the policy in the
docs and the release-beta skill, reversing the docs side of 28415b354.

* Spell out in-place beta overwrite in the promotion checklist

The stable checklist said only "update CHANGELOG.md", so a promotion
followed by the letter could stack a fresh entry on top of the
-beta.N block — the stale heading the policy forbids. Make the
promotion path overwrite-in-place explicit, matching the beta checklist.
2026-06-17 15:35:25 +08:00
Mohamed Boudra eca0a5bf67 Let manual update checks bypass rollout
Automatic desktop update checks still respect rollout admission. Manual checks carry an explicit intent through the app and desktop updater service, and the up-to-date state now shows when the last check completed.
2026-06-09 15:47:30 +07:00
Mohamed Boudra de5fa4dc36 Publish beta npm packages under beta tag 2026-06-04 11:53:58 +07:00
Mohamed Boudra 6f6c939624 Pin ACP catalog entries to current versions 2026-06-03 14:08:56 +07:00
Mohamed Boudra 7fb3dda20c Add detached agents and heartbeat scheduling (#1266) 2026-06-01 14:07:31 +08:00
Mohamed Boudra 357c31d16e Clarify mobile release completion checks 2026-06-01 10:30:39 +07:00
Mohamed Boudra 1821f2853a Fix release prep checks 2026-05-31 22:05:18 +07:00
Mohamed Boudra e4188f5222 Document the two-step release flow
The release has two steps: preparation, which the agent does locally and
reversibly, and go-ahead, which only the user authorizes. Last-minute
changes always need approval, code changes never bundle into the
changelog or release commit, and a sanity-check finding is information
for the user — not a directive for the agent to act on.
2026-05-28 18:08:54 +07:00
Mohamed Boudra 28415b3542 docs(release): make betas silent, add release-beta/stable skills 2026-05-21 10:20:21 +07:00
Mohamed Boudra 1b9861846c Improve 0.1.78 changelog and add user-facing examples to release docs 2026-05-18 17:58:49 +07:00
Mohamed Boudra 69fc6fe754 Document the positive submission-verification path (eas build:view Logs URL) 2026-05-18 10:16:42 +07:00
Mohamed Boudra 1b2a28be47 Drop eas submit:list references from release/android docs 2026-05-18 10:15:10 +07:00
Mohamed Boudra 665d9cedb5 Drop bogus eas submit:list from release docs and heartbeat checks 2026-05-18 10:14:29 +07:00
Mohamed Boudra 0d0012959a Lock babysit pattern: heartbeat to self, every 15m maxRuns 8 2026-05-18 09:59:00 +07:00
Mohamed Boudra 77b92b58f7 Drop trailing periods from changelog and fix mobile release docs
- Strip end-of-bullet periods from CHANGELOG.md (whole file)
- Tighten 0.1.77 TLS bullet to drop LAN/public explanation
- Release docs: drop release-mobile.yml references (workflow does not exist),
  add EAS mobile-build babysitting section using the EAS CLI, clarify that
  releases are always patch, clarify that "stable" means stable
- Changelog style guide: no trailing periods, one sentence per bullet, lead
  with capability not mechanism
2026-05-18 09:33:46 +07:00
Mohamed Boudra 1f79c4d039 Bump default desktop rollout to 36h 2026-05-15 14:47:42 +07:00
Mohamed Boudra c40e1f03db docs: deep audit pass — fix drift across every doc, rebase coding-standards on /unslop
Each doc verified against current code; stale claims fixed in place.

- architecture: handshake/binary-frame/route/module-table corrections
- data-model: atomic-write claim narrowed, missing daemon files/fields added
- development: db:query removed (SQLite/Drizzle gone), tmux→concurrently+portless, PASEO_HOME split
- unistyles: withUnistyles(Icon) is the dominant pattern; new Animated.View+dynamic-styles iOS gotcha
- SECURITY: bearer-token auth, DNS-rebinding allowlist semantics, ephemeral phone keypair, wire format
- glossary: Project-checkout rename has shipped
- providers: claude-acp not built-in, Pi/mock, async isCommandAvailable, interface drift
- coding-standards: rewritten as compressed /unslop adaptation
- product/release/testing/custom-providers/android/mobile-testing/ad-hoc-daemon-testing/file-icons/design: smaller corrections
2026-05-09 11:35:26 +07:00
Mohamed Boudra 6e75c72492 chore: refresh lockfile dev markers, document release gotcha
`release:prepare` runs `npm install` which churns optional-dep `dev`
markers in package-lock.json. That dirties the tree before the
`npm version` step in `version:all:*`, and the pre-commit format hook
rejects a lockfile-only commit because oxfmt internally skips
package-lock.json. Document the run-format/lint/typecheck-first
guardrail in docs/release.md.
2026-05-08 20:31:26 +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 a64be66353 docs(release): credit commit author over PR opener
Squash commits keep the original commit author, but `gh pr view N --json author` returns the PR opener — using that field silently mis-credits work to the maintainer who landed the PR (and the skip-@boudra rule then drops the credit). Document the `--json commits | unique logins` query as the source of truth for attribution.
2026-05-02 12:12:44 +07:00
Mohamed Boudra dec47d72d9 docs: lowercase internal docs + migrate website docs to public-docs/ (#634)
* docs: rename to lowercase + drop leftover plans

Rename docs in docs/ to lowercase kebab-case for consistency and update
all references in CLAUDE.md, CONTRIBUTING.md, CHANGELOG.md,
packages/server/CLAUDE.md, and inter-doc links.

Drop two leftover design plan docs:
- docs/ATTACHMENT_BASED_REVIEW_CONTEXT_PLAN.md
- docs/plan-approval-normalization.md

* docs: drop stale uppercase entries from case-insensitive rename

* feat(website): power /docs from public-docs/ markdown tree

Move website docs out of TSX route components and into a root-level
public-docs/ directory of plain markdown files with frontmatter
(title, description, nav, order).

- Add packages/website/src/docs.ts loader using import.meta.glob with
  ?raw to compile the markdown into the bundle at build time.
- Replace the 9 hand-written docs/*.tsx routes with a single $.tsx
  catch-all that renders any slug via react-markdown.
- Drive the docs sidebar nav from frontmatter order/nav.
- Auto-discover docs routes in vite.config.ts so the sitemap stays in
  sync without manual edits.

* fix(website): bind dev server to 0.0.0.0 so port collisions trigger fallback

`host: "127.0.0.1"` (or unset) lets macOS coexist with another process
holding an IPv6 dual-stack `*:8082` socket, so Vite never sees
EADDRINUSE and silently binds alongside it. Forcing IPv4 wildcard
makes the conflict real, and Vite's default `strictPort: false`
falls through to the next free port.

* fix(website): restore docs page styling after markdown migration

Add a .docs-prose class that mirrors the styling the original
docs/*.tsx components hand-rolled (h1/h2/h3 sizes, paragraph/list
spacing, link colors, code blocks, callout-style blockquotes).

ReactMarkdown was emitting unstyled HTML because the previous
wrapper class only had inline-code rules — headings and code
blocks fell back to user-agent defaults.
2026-04-30 17:27:15 +08:00