From d1108698bb2d14a4425353b3c3cb91d50860f2b9 Mon Sep 17 00:00:00 2001 From: David Young Date: Wed, 11 Nov 2026 14:42:30 -0700 Subject: [PATCH] Add the plan for merging Pop!_OS support into configure A Claude Code skill (/coredesktop-pop-merge) with the plan for folding connector-popos, the Pop!_OS port of configure, back in here behind a platform layer, so one Linux configure runs on Arch and Pop!_OS. It records the facts verified while porting and the decisions still open, so the work can be picked up later. Co-Authored-By: Claude Opus 5.5 --- .claude/skills/coredesktop-pop-merge/SKILL.md | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 .claude/skills/coredesktop-pop-merge/SKILL.md diff --git a/.claude/skills/coredesktop-pop-merge/SKILL.md b/.claude/skills/coredesktop-pop-merge/SKILL.md new file mode 100644 index 0000000..c25ae8c --- /dev/null +++ b/.claude/skills/coredesktop-pop-merge/SKILL.md @@ -0,0 +1,193 @@ +--- +name: coredesktop-pop-merge +description: Plan and progress for merging Pop!_OS support (the connector-popos port) into CoreDesktop's configure, so one Linux configure runs on Arch and Pop!_OS with COSMIC. Use when resuming, continuing, checking the status of, or changing the Pop!_OS/CoreDesktop merge, the platform layer (configure.d/lib/platform.sh), or connector-popos. +--- + +# Merge Pop!_OS support into CoreDesktop's configure + +## Where things stand + +Work out the current state before doing anything; this plan was written on 2026-11-11 and may be partly done: + +``` +git -C ~/Projects/coredesktop fetch && git -C ~/Projects/coredesktop log --oneline origin/main -20 +ls ~/Projects/coredesktop/configure.d/lib/platform.sh ~/Projects/coredesktop/pop 2>/dev/null +git -C ~/Projects/connector-popos log --oneline -5 +curl -s -o /dev/null -A curl/8 -w '%{redirect_url}\n' https://federated.sh/pop +``` + +Map what you find onto the steps below, tell the user which step is next, and confirm before starting it. + +### Repositories + +| Repo | Local | What | +|------|-------|------| +| `Federated_Computer/coredesktop` | `~/Projects/coredesktop` | Arch + GNOME desktop setup; `configure` and `configure.d/` are one part of it | +| `Federated_Computer/connector-popos` | `~/Projects/connector-popos` | Standalone Pop!_OS port of `configure`, published 2026-11-11 (commit `bc07e1d`, MIT). To be archived after the merge. | +| `Federated_Computer/connector-macos` | `~/Projects/connector-macos` | macOS port. Stays separate: bash 3.2, no jq/python, profiles, launchd, Seatbelt. | + +All on `https://gitea.federated.computer`. Pushing uses the cached git credentials. git's credential cache socket is blocked inside Claude Code's sandbox, so git push needs the sandbox turned off for that command. + +### Why merge + +connector-popos is a fork, not a port. Measured against CoreDesktop: 10-core 92% unchanged, storage 93%, ai-servers 95%, sandbox item 97%, and goa-account, email-watch, setup-printers.sh, nextcloud.sh, mdns.sh and json.sh 94–100%. CoreDesktop's configure is changing fast (12+ commits since late October), so a fork drifts. That already happened twice: the `step` name clash (fixed in connector-macos, not CoreDesktop), and the Online Accounts 3.50 attention fix (only in connector-popos). macOS shares little code (10-core 37%, mdns 27%) and stays separate. + +## Facts verified while porting (don't re-derive) + +- **Pop!_OS:** + - 24.04 LTS with COSMIC, released 2025-12-11; 26.04 was still unreleased in August 2026. + - Pop's apt repo has cosmic-files 1.11. + - pop-desktop/cosmic-session pull in gnome-keyring and libsecret, but **not** gnome-online-accounts or Evolution. + - GOA, davfs2, restic, rclone and the rest come from Ubuntu noble. +- **COSMIC has no Online Accounts.** The user chose GNOME Online Accounts + Evolution, with configure adding accounts through `goa-account` exactly as on Arch. Thunderbird was rejected, because the password-changed flow and the email watcher can't be ported to it. +- **GOA 3.50 (Ubuntu noble) works headless with `goa-account`:** add, exists, pause/paused, update, check, remove and disabled all pass. But it sets `AttentionNeeded` (`NotAuthorized`) for **unreachable servers too**, for both Nextcloud and mail. So "needs attention" must not be read as "wrong password". The email watcher is already safe: it confirms with Nextcloud, and skips when Nextcloud can't be reached. +- **COSMIC session:** + - `cosmic-session.target` binds `graphical-session.target` and wants `xdg-desktop-autostart.target`, so user units with `WantedBy=graphical-session.target` and XDG autostart entries both work. + - cosmic-notifications supports `notify-send --action`. + - `cosmic-term -e ` runs a command. +- **COSMIC Files sidebar:** + - cosmic-config `~/.config/cosmic/com.system76.CosmicFiles/v1/favorites`, a RON list of `Home|Documents|Downloads|Music|Pictures|Videos|Path("..")|Network(uri:,name:,path:)|Named(path:,name:)`. + - `Named` exists since epoch 1.7. + - If the file is missing, cosmic-files uses the six defaults, so write those first. + - Helper: `connector-popos/configure.d/lib/cosmic-favorites`. +- **davfs2 on Ubuntu:** + - User mounts need `mount.davfs` setuid. Set it with `echo "davfs2 davfs2/suid_file boolean true" | sudo debconf-set-selections`, before install, or followed by `dpkg-reconfigure -f noninteractive davfs2`. + - The group is `davfs2`; Arch uses `network`. +- **Ubuntu noble's versions:** restic 0.16.4 and rclone 1.60.1, enough for `rclone::webdav:` and `rclone obscure -`. Pop's Node.js is too old for srt (needs 22.12+), so download the LTS from nodejs.org, checking SHASUMS256. Current Node (v26) needs **`libatomic1`**. +- **The sandbox on Ubuntu 24.04:** bubblewrap may be blocked by `kernel.apparmor_restrict_unprivileged_userns=1`. The fix is an AppArmor profile for `/usr/bin/bwrap` with `userns,`. It's unverified whether Pop sets this; check on a real machine. +- **Package paths:** Ubuntu's libnss-mdns uses `mdns4_minimal`, not `mdns_minimal`. GTK's CUPS backend is at `/usr/lib/*/gtk-3.0/*/printbackends/libprintbackend-cups.so`. `fusermount3` is in `/usr/bin`. The keyring's SSH agent is at `$XDG_RUNTIME_DIR/keyring/ssh`, or `gcr/ssh`. +- **Installers:** Tailscale's `install.sh` handles `ID=pop`. mise's apt repo is `https://mise.jdx.dev/deb stable main`, with the key at `https://mise.jdx.dev/gpg-key.pub`. +- **federated.sh** is Caddy. Its `/mac` rule: + - matches case-insensitively, with or without a trailing slash, ignoring the query; paths below it fall through + - sends a User-Agent starting with `Mozilla` to the repo page, and everything else to the raw `install.sh` + - `/pop` didn't exist on 2026-11-11 (it fell through to CoreDesktop's Arch installer); a Caddy skill to add it was handed to the server's agent, pointing at connector-popos + +## Decisions (defaults; the user can change them) + +1. **Pop uses CoreDesktop's names:** `~/.local/share/coredesktop`, `~/.config/coredesktop`, `coredesktop-*` units, `coredesktop backup` keyring attributes, `/etc/coredesktop/smb`. Arch users then need no migration. connector-popos used `federated-connector-*` names, so anyone who installed it needs a one-time migration, or a reinstall. +2. **Pop installs with git**, cloning into `~/.local/share/coredesktop`, so `update` is a `git pull`. This replaces connector-popos' tarball swap. +3. **Pop gets its own `pop/update`:** pull, reinstall the commands, refresh the user units, restart the email watcher, and run migrations marked for Pop. CoreDesktop's `update` runs Arch-only hooks; Pop's own updater handles the system. +4. **Items install what's missing**, with `pkg_ensure`. On Arch everything is there, so this does nothing. +5. **Hold the federated.sh/pop switch until step 6**, or add a migration from connector-popos' paths. + +Still open; ask the user: +- Has CoreDesktop's owner signed off? The merge touches `configure` while it's being actively changed. +- Branding on Pop: should users see "CoreDesktop" or "Federated Connector"? + +## Design: `configure.d/lib/platform.sh` + +`configure` sources it; it sets `PLATFORM=arch|pop` from `/etc/os-release`. An Ubuntu-like system counts as `pop`, with a "made for Pop!_OS" warning. It provides: + +- `pkg_installed`, `pkg_ensure ...` and `pkg_install`: pacman on Arch, dpkg/apt on Pop. They take Pop's (Debian) names, with a table of Arch names: + + | Pop | Arch | + |-----|------| + | `avahi-utils` | `avahi` | + | `libsecret-tools` | `libsecret` | + | `libatomic1` | `gcc-libs` | + | `python3-gi` | `python-gobject` | + | `gir1.2-secret-1` | `libsecret` | + | `libnotify-bin` | `libnotify` | + | `smbclient` | `smbclient` | + +- `flatpak_installed` and `flatpak_ensure`. +- `sidebar_add`, `sidebar_remove` and `sidebar_has`. Both platforms write GTK bookmarks; Pop also writes COSMIC Files' favorites. +- `DAVFS_GROUP` (`network` or `davfs2`) and `davfs2_ready` (setuid through debconf on Pop; nothing on Arch). +- `element_installed` and `element_config`: the `im.riot.Riot` Flatpak keeps it at `~/.var/app/im.riot.Riot/config/Element/config.json`, otherwise `~/.config/Element/config.json`. +- `goa_ready` and the accounts text: "Online Accounts (Settings)" on Arch, "shown in Evolution" on Pop, which also installs gnome-online-accounts, evolution, python3-gi and gir1.2-secret-1. +- `install_tailscale`: pacman, or Tailscale's `install.sh`, downloaded then run. +- `install_mise` and `mise_activated`: on Arch, mise comes from pacman and `shell/bashrc` activates it; on Pop, mise's apt repo and a block in `~/.bashrc`. + +Done in place, not through the layer: +- `system/run-in-terminal` tries `cosmic-term -e` first. +- `system/sftp-mount` also tries `keyring/ssh`. +- `setup-printers.sh` checks dependencies and GTK's backend per platform, and accepts `mdns4_minimal`. + +## Steps (one reviewable PR each) + +### 1. Platform layer, Arch unchanged (pure refactor) +- Add `platform.sh` with the Arch side only. +- Change `10-core.sh`, `15-tailscale.sh`, `20-backup.sh`, `40-languages.sh`, `60-storage.sh` (`sudo pacman -S sshfs` becomes `pkg_ensure`) and `setup-printers.sh` to call it. +- Drop the `is_installed` checks that only hid an item when its tools were missing (backup, ai-servers, printers, storage, tailscale); the item now offers to install them. +- Tests: + - bats tests for `platform.sh`, stubbing pacman, dpkg and apt as `tests/test_helper.bash` already does + - `make lint`, `bats tests` + - CoreDesktop's VM smoketest quick tier (`coredesktop-dev smoketest run`, through the coredesktop-dev sibling), to show Arch is unchanged + +### 2. Fixes for both platforms +- **`test_account` in `10-core.sh`:** + - drop the `"$GOA_ACCOUNT" attention` branch + - keep `email-watch --check-password` (Nextcloud) before `goa-account check` + - update the comment: 3.50 flags unreachable servers. On Arch's 3.58 this only adds one Nextcloud sign-in during Test a Core. +- **Rename `step` to `core_step`** in `10-core.sh`, including the `[ ... ] && step element|tally` lines. +- **Comment fixes:** the 3.58 notes in `configure.d/lib/goa-account` and `system/email-watch`. + +### 3. Pop's side of the layer +- Fill in `platform.sh` for Pop. +- Copy from connector-popos: + - `configure.d/lib/cosmic-favorites` + - the davfs2 setuid step + - the Tailscale and mise apt-repo installs + - the Element Flatpak path +- `configure`: a menu title and the not-Pop warning per platform; refuse to run as root. +- Docs: what's different on Pop (Evolution, COSMIC Files, AppArmor) and what needs a real Pop machine. +- connector-popos' README "Differences from CoreDesktop" lists everything this step must cover. + +### 4. The agents item, sharing the sandbox setup +- Move `sandbox/setup.sh`'s logic into functions in `sandbox/lib.sh`, used by both `setup.sh` (Arch, `updates.d/72-sandbox.sh`) and a new `configure.d/30-agents.sh` (from `connector-popos/configure.d/30-agents.sh`): + - Claude Code's sandbox defaults, plus `claude.sh`'s notification hooks + - the Hermes gateway drop-in (keep the name `coredesktop-sandbox.conf`) + - the Cline Desktop entry +- Renumber `30-claude`, `31-opencode` and `32-hermes` to `31`, `32` and `33`. Item names don't change. +- **`30-agents` on Arch:** shows done. +- **`30-agents` on Pop:** installs the agents with their own installers, installs Node.js and srt under `~/.local/share/coredesktop/tools` (`lib/tools.sh`), adds `libatomic1`, the PATH block and the AppArmor offer. +- `srt_path` finds `~/.local/bin/srt` (Arch's npm install) or the tools one. `sandbox/agent` uses `agent_path` (connector-popos `configure.d/lib/agents.sh`). +- `sandbox/config/base.json`: add `ubuntu.com`, `*.ubuntu.com`, `pop-os.org`, `*.pop-os.org`, `system76.com` and `*.system76.com` next to Arch's, and `~/.config/evolution`, `~/.local/share/evolution`, `~/.cache/evolution`, `~/.config/goa-1.0` and `~/.thunderbird` to `denyRead`. + +### 5. Installing and updating on Pop +- `pop/install.sh`: adapt from `connector-popos/install.sh`. + - preflight: apt, not root, sudo group, network + - `apt install git curl jq libsecret-tools python3-gi gir1.2-secret-1 libnotify-bin` + - clone, `install_script` for `configure` and `pop/update` into `~/.local/bin` + - put `~/.local/bin` on PATH at the top of `~/.bashrc` + - mark the existing migrations as done + - offer configure, reading answers from `/dev/tty` and apt's stdin from `/dev/null` +- `pop/update`: `git pull --ff-only`, reinstall the commands, refresh the `coredesktop-*` units configure installed, restart the email watcher, run Pop migrations. +- **Migrations:** `run_migrations` (`utils.sh`) runs only those whose header has `# platforms:` naming the current platform; unmarked ones are Arch only. Check it doesn't pull in Arch-only parts of `utils.sh`; if it does, move it to `lib/migrations.sh`. +- **Tests:** move `connector-popos/smoketest/` to `smoketest/pop/`, rename the paths and units, and add it and `bats tests` to `.gitea/workflows` (the runner is `ubuntu-latest`). + +### 6. Switch over +- After a manual pass on a real Pop!_OS 24.04 machine (below), point federated.sh/pop at `https://gitea.federated.computer/Federated_Computer/coredesktop/raw/branch/main/pop/install.sh`, with the browser redirect going to the repo page. That's a change to the Caddy skill's two targets. +- Archive connector-popos, with a README pointer. + +## Verification +- `make lint` and `bats tests` on every PR. +- The Arch VM smoketest after steps 1, 2 and 4. +- The Pop Docker smoketest (`smoketest/pop/run --tier all`) after steps 3–5. Docker needs the sandbox turned off for that command. Its scenarios: + - install and update + - the menu + - GOA 3.50 + - Superpanel, Element, the sidebar, davfs2's secret + - restic and rclone against a local `rclone serve webdav` + - the srt sandbox, `--privileged` + - davfs2 setuid, sshfs, GTK print backend, mise +- **Manual, on real Pop!_OS**, which containers can't check: + - COSMIC Files showing the sidebar entries + - Evolution against a real Core + - the davfs2 mount after logging out and in + - the backup timer and the email watcher's notification, which opens `configure core` in COSMIC Terminal + - Tailscale with a Core's headscale + - real SMB and SFTP mounts + - whether the AppArmor profile is needed + +## Risks +- **Arch regressions:** step 1 changes no behavior and is checked on the VM first. +- **Collisions with ongoing configure work:** land steps 1–2 quickly, and tell contributors that new item code should go through `platform.sh`. +- **`update` means different commands** on Arch and Pop. Document both. + +## Effort +About 1.5–2 days: +- steps 1–2: half a day +- steps 3–4: half a day to a day +- step 5: half a day +- step 6 and the manual pass: an hour or two, plus a Pop machine