docs: the Linux package ships iced, not GTK - #318
Conversation
`main` has shipped the iced UI as the Linux package's `/usr/bin/roost` since the deb swap, but the docs still described gtk4-rs as the Linux UI. The worst case was `README.md`, which `packaging/nfpm.yaml` installs to `/usr/share/doc/roost/README.md`: the package shipped documentation contradicting its own binary, and its only build-from-source instruction for Linux built `roost-linux` — not the UI a user actually gets. Corrected throughout, to one consistent shape: two shipped platform products (Swift + AppKit on macOS, iced on Linux) and three in-repo UI implementations. Deliberately NOT "GTK is gone" — `crates/roost-linux` still builds and `gtk-build` plus all three `e2e-gtk*` lanes still gate every PR. Only the package changed. `architecture.md`'s Stack table needed restructuring rather than a one-row edit: every Linux cell named GTK, so correcting only "Window + chrome" would have left the table more self-contradicting than before. It is now three columns, and the rows that are genuinely shared point at their real `roost-engine`/`roost-ipc` paths. That surfaced a stale path the old table had carried for a while — `crates/roost-linux/src/daemon/pty.rs` no longer exists; the PTY has moved to `crates/roost-engine/src/pty.rs`, shared by both Linux UIs. `CLAUDE.md` cited the same dead path. vision.md gets exactly two edits — the current-state intro and the `## Architecture` mermaid diagram. Its DL-* decision-log entries are untouched: they are historical rationale, and rewriting them would falsify the record. Also retires "Iced POC" as a label for a UI that now ships, in the places that describe current state (the dev profile is now "iced dev build"). Historical plan documents keep their original wording. Verified by a full `grep -rn "gtk4-rs\|roost-linux\|Iced POC\|poc/iced"` sweep over every tracked markdown file with a written disposition for each surviving hit, rather than a grep for the wording already fixed. Every new file path cited was checked to exist. `mkdocs build` succeeds; `--strict` surfaces only pre-existing warnings, confirmed unchanged by this diff — worth stating because `docs.yml` has no pull_request trigger, so nothing else builds the site before merge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SgxiEBQTqgNjPswKqcs12d
`ut_socket_for gtk` produced `/tmp/roost-<uid>/roost/roost.sock` when `XDG_RUNTIME_DIR` was unset — a doubled segment the real resolver never emits. `crates/roost-ipc/src/paths.rs` yields `/tmp/roost-<uid>/roost.sock`. The arm also accepted an empty or relative `XDG_RUNTIME_DIR`, where the resolver requires absolute and otherwise falls back. The sibling `iced` arm was already correct; the gtk arm now mirrors it. This matters more than it did: the packaged iced UI runs on the gtk profile, so this is the path tooling would use against a real user install. Covered by a real test rather than a one-off transcript. The new `tools/roosttest_unit/test_socket_paths.py` sources `lib.sh` in a subprocess and asserts exact output for all four `XDG_RUNTIME_DIR` states (absolute, unset, empty, relative) across both Linux targets — the semantics being that an invalid value is ignored with a fallback, not an error. It stubs `uname` so the non-Darwin branch is exercised deterministically on a Mac too, and it lives where `ci.yml`'s `harness-unit` job already runs it. Confirmed it fails against the unfixed script: three of the four gtk cases show the doubled segment. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SgxiEBQTqgNjPswKqcs12d
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 22 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (16)
Comment |
The cloud review reported `pass` while its body said "Review limit reached" and it had reviewed nothing — the false-pass the plan's brief warns about. The local CLI reviewed all 16 files and found three real issues, two of them misses in this branch's own diff. vision.md's command-core section still read "One contract, two implementations", named only Swift and GTK, and ended at "Core Graphics vs Cairo" — the same class of stale claim already fixed in CLAUDE.md's north star, and the reason scoping vision.md to "two places" was too narrow. Its parity question further down said "both implementations" too. Both now name all three, and record that the two Rust UIs additionally share `roost-engine`. The DL-* decision log remains untouched. config.md contradicted itself: the settings table listed `link-modifier` for "the GTK and Iced apps" while the setting's own scope note said "the GTK app only". Verified against the source — `link_modifier_held` is implemented in `crates/roost-iced/src/app.rs` — so the scope note was the stale half. Fixed, and the file's portability claim now says plainly that a few settings are honored by only some UIs, with the per-setting section as the authority. Not adopted: the suggestion to document iced's threading contract alongside Mac and GTK. Real gap, but it asks for new material about single-owner `vt_write` access and the `EngineReady` hand-off that this docs-correction pass has not verified, and asserting an unverified threading rule in the governing docs is worse than the omission. Noted as follow-up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SgxiEBQTqgNjPswKqcs12d
Plan 023, workstream B (+ the third W-D bug). Part 3 of 3 — #316 merged,
#317 in flight.
The problem
mainhas shipped the iced UI as the Linux package's/usr/bin/roostsince the deb swap, but the docs still described gtk4-rs as the Linux UI.
The worst case:
README.mdis installed into the package itself(
packaging/nfpm.yaml→/usr/share/doc/roost/README.md). So the packageshipped documentation contradicting its own binary — and its only
build-from-source instruction for Linux built
roost-linux, not the UI auser actually gets.
CLAUDE.md, which every future session reads first, saidthe same in five places.
The rule this follows
Where a doc describes current state: the Linux package ships the iced UI;
GTK remains in-repo as the development/parity implementation. Deliberately
never "GTK is gone" —
crates/roost-linuxstill builds, andgtk-buildplus all three
e2e-gtk*lanes still gate every PR. Only the packagechanged.
For the governing docs, the sharper framing: two shipped platform products
(Swift + AppKit on macOS, iced on Linux) vs three in-repo UI
implementations.
What changed
README.md(both the claim and the build-from-source block),docs/index.md,CLAUDE.md(×5),docs/reference/architecture.md(×4),docs/development/vision.md(×2),config.md,claude-testing.md,setup.md,crates/README.md, theMakefileheader, and theCHANGELOG.mdheader's stale
/release:releasecommand name.architecture.md's Stack table needed restructuring, not a one-row edit.Every Linux cell named GTK, so correcting only "Window + chrome" would have
left the table more self-contradicting than before. It is now three columns
(macOS / Linux-GTK-dev / Linux-iced-shipped), and the rows that are genuinely
shared point at their real
roost-engine/roost-ipcpaths.That surfaced a stale path the old table had carried for a while:
crates/roost-linux/src/daemon/pty.rsno longer exists — the PTY moved tocrates/roost-engine/src/pty.rs, shared by both Linux UIs.CLAUDE.mdcitedthe same dead path. Neither was in the swept inventory; both are fixed.
vision.mdgets exactly two edits — the current-state intro and the## Architecturemermaid diagram. Its DL-* decision-log entries areuntouched: they are historical rationale, and rewriting them would falsify the
record.
Also retires "Iced POC" as a label for a UI that now ships, in the places that
describe current state (the dev profile is now "iced dev build"). Historical
plan documents keep their original wording.
Plus the third W-D bug
tools/screenshot/lib.sh'sut_socket_for gtkproduced/tmp/roost-<uid>/roost/roost.sockwhenXDG_RUNTIME_DIRwas unset — adoubled segment the real resolver never emits (
paths.rsgives/tmp/roost-<uid>/roost.sock). It also accepted an empty or relativeXDG_RUNTIME_DIRwhere the resolver requires absolute. The siblingicedarmwas already correct; gtk now mirrors it.
This matters more than it did: the packaged iced UI runs on the gtk
profile, so this is the path tooling would use against a real user install.
Covered by a real test rather than a one-off transcript.
tools/roosttest_unit/test_socket_paths.pysourceslib.shin a subprocessand asserts exact output for all four
XDG_RUNTIME_DIRstates (absolute,unset, empty, relative) across both Linux targets — the semantics being that
an invalid value is ignored with a fallback, not an error. It stubs
unameso the non-Darwin branch is exercised deterministically on a Mac too, and it
lives where
ci.yml'sharness-unitjob already runs it. Confirmed it failsagainst the unfixed script: three of the four gtk cases show the doubled
segment.
Verification
grep -rn "gtk4-rs\|roost-linux\|Iced POC\|poc/iced"sweep over everytracked markdown file, with a written disposition for every surviving
hit (
fixed/correct-as-historical/correct-as-dev-UI/out-of-scope-archive) — 111 hits. A grep for wording already fixed wouldnot be a gate; this is.
mkdocs buildsucceeds.--strictsurfaces only pre-existing warnings,confirmed unchanged by this diff via
git stash. Worth stating becausedocs.ymlhas nopull_requesttrigger — it only runs on push to main,so nothing else builds the site before merge, and a broken link would first
appear as a failed Pages deploy afterwards.
python3 -m unittest discover -s tools/roosttest_unit— 50 tests pass(8 new).
shellcheck tools/screenshot/lib.shclean.Scope notes
Two things beyond the brief's swept inventory, both flagged deliberately:
architecture.md'spoc/icedparagraph (false in both halves after themerge, and it sat two lines below a line being corrected), and the six
additional current-state contradictions the plan's panel review surfaced —
including
README.md's build block, which is the highest-value one and livesin the file the package ships.
Left alone on purpose:
installation.md,paths.md's profile table,CLAUDE.md's GTK4 library-preference row, vision.md's decision log, and thearchived/historical plan documents.
No dependency, privacy, or secret impact. Prose plus one shell fix and one new
unit test; no production code touched.
Plan 023 §D2 — the pinned wording rule and gate
D2.0 — The brief supplied a swept list and asked that it be executed
rather than re-derived. The panel found six more current-state
contradictions; they are adopted because the brief's own definition of done is
"no documentation shipped in the package, and none of the governing docs,
still claims GTK is the Linux UI", and
README.md:45— the only Linux buildinstruction in the file installed into the
.deb— fails that test squarely.D2.3 — architecture.md:
:3(drop "production", name threeimplementations),
:13-24(the whole Stack table, not just the header row— fixing one row makes the rest more contradictory),
:39(addroost-iced/to the repo-layout tree).
D2.7 — the gate is a sweep, not a phrase-grep. The first draft's gate
searched for wording already fixed. Replaced with a full sweep plus a written
disposition for every surviving hit, and
mkdocs build --strict.D4.2 —
ut_socket_for gtkgets precise expected outputs for all fourXDG_RUNTIME_DIRstates, and a durable regression intools/roosttest_unit/— reversing the first draft's "no test home exists".🤖 Generated with Claude Code
https://claude.ai/code/session_01SgxiEBQTqgNjPswKqcs12d