<feed xmlns='http://www.w3.org/2005/Atom'>
<title>archsetup/tests/installer-steps, branch claude/hungry-franklin-09fffc</title>
<subtitle>Builds a full dev workstation from a bare Arch Linux install.
</subtitle>
<id>https://git.cjennings.net/archsetup/atom?h=claude%2Fhungry-franklin-09fffc</id>
<link rel='self' href='https://git.cjennings.net/archsetup/atom?h=claude%2Fhungry-franklin-09fffc'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/'/>
<updated>2026-10-17T12:07:25+00:00</updated>
<entry>
<title>feat(keyring): ship a patched gnome-keyring and install it from the repo</title>
<updated>2026-10-17T12:07:25+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-10-17T12:07:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=cd6e11b46ecf2b56bf63d6c11886dccc70875e10'/>
<id>urn:sha1:cd6e11b46ecf2b56bf63d6c11886dccc70875e10</id>
<content type='text'>
gnome-keyring 48 through 51.1 aborts when a client's first OpenSession is dispatched before the daemon has created its per-client record. Each abort drops the unlocked state and the next request pops the password dialog. On ratio that happened about three times a day from 2026-10-11, when the ChatGPT desktop app's codex app-server started bursting keyring reads. The same-day glib and keyring upgrades were a coincidence, since 50.0 reproduces it too. Upstream's fix (merge request !112) has sat unmerged since August.

packages/gnome-keyring is Arch's recipe for 1:51.1-1 built from GNOME's tarball plus one patch. It registers the client at the point of use and returns a real D-Bus error instead of completing OpenSession with a NULL body. It resolves a collection alias only after the caller's session exists. It also locks the alias table so the worker-thread filter can't read an entry the main thread is freeing, a pre-existing defect that AddressSanitizer confirmed. I chose pkgrel 1.1 so stock sorts below the rebuild and any future Arch or upstream fix replaces it on a normal upgrade. Nothing pins the package.

install_gnome_keyring_fix replaces the plain stock install, which pacman's --needed would otherwise use to downgrade the rebuild on every re-run. It installs stock only when no gnome-keyring is present, compares versions with vercmp, then stages the recipe into the source dir and builds it with makepkg as the user. The rebuild is a no-op, anything newer skips with a visible note, and a failed build leaves stock in place. I also corrected the keyring-dir comment: the default alias only picks the collection and doesn't unlock anything under autologin.

working/keyring-crash holds the probe, the guest fixture and runners, and the deployment script with backup and rollback. status.org there records the cause and results. Stock aborts on the probe's first batch. The patched daemon, its sanitizer build and the installed package pass every mode, and the upstream suite scores the same for both.
</content>
</entry>
<entry>
<title>feat: install the ChatGPT desktop app from OpenAI's pacman repo</title>
<updated>2026-10-12T06:19:10+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-10-12T06:19:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=e530fd597b62bda520f9804be7da216eea582750'/>
<id>urn:sha1:e530fd597b62bda520f9804be7da216eea582750</id>
<content type='text'>
OpenAI publishes the ChatGPT (Codex) desktop app for Arch as chatgpt-bin from its own signed pacman repository, and that's how ratio and velox got it on 2026-10-11. configure_openai_chatgpt_repo reproduces that setup. It fetches the repository signing key and accepts it only when the primary fingerprint matches the pin OpenAI's installer carries. It writes the same drop-in bytes OpenAI's installer writes, so a machine that installer already configured is left alone. Then it adds the Include to pacman.conf and refreshes the databases. supplemental_software installs chatgpt-bin next to claude-desktop.

I took the repository over the AUR chatgpt-desktop repackage: the repo keeps the app on ordinary pacman upgrades under OpenAI's signature, and the AUR package conflicts with chatgpt-bin on a machine already using the repo.

An untrusted key imports nothing and leaves pacman.conf alone. With the Include present and the key untrusted, TrustedOnly would fail every later pacman transaction. The step returns non-zero instead and chatgpt-bin is skipped.
</content>
</entry>
<entry>
<title>feat(audio): ship the Framework 13 AMD internal-mic workaround</title>
<updated>2026-10-06T19:58:40+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-10-06T19:58:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=5189b7cdc7647f92382ddda3ca7d1a30fcffa4ce'/>
<id>urn:sha1:5189b7cdc7647f92382ddda3ca7d1a30fcffa4ce</id>
<content type='text'>
On the Framework 13 with AMD Ryzen AI 300 the kernel's ACP PDM digital-mic path returns a constant full-scale rail instead of audio. With UCM on, that broken DMIC is the only internal mic PipeWire offers, so the built-in microphone is dead in every app. The new step installs a WirePlumber drop-in that turns UCM off and disables the standalone PDM card so nothing can select it. Without UCM the ALC285 falls back to its analog-stereo profile, whose internal-mic pin carries real audio.

I gated it on DMI rather than on the acp-pdm-mach card or the hostname. The card exists on every AMD laptop with a PDM mic and stays present after the upstream fix lands, so its presence says nothing about whether the workaround belongs. The fix belongs to the board, not to one machine. The match needs all three of Framework, "Laptop 13" and "AMD Ryzen AI 300". That rules out the Framework Desktop ("AI Max 300") along with the Intel 13, the Ryzen 7040 13 and the 16. The rule inside the drop-in matches the PDM card by name pattern for the same reason: the gate covers the whole board family, so the rule can't pin the one PCI path velox enumerates.

The drop-in ships as a file under configs/, so a re-run refreshes it and deleting it plus a wireplumber restart reverts the machine. The installer doesn't restart wireplumber itself: there's no user session bus during install, so the drop-in applies when wireplumber next starts.

The audio failure taxonomy gains a row for the bug and a Cluster 5 note, so the audio doctor's use-ucm remedies treat the installed drop-in as the fix rather than as an offending config to remove.
</content>
</entry>
<entry>
<title>fix(tlp): install the bluetooth resume hook where systemd-sleep looks</title>
<updated>2026-10-06T04:34:54+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-10-06T04:33:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=1e134f5022f626ed36279915369c06fa6df0e76e'/>
<id>urn:sha1:1e134f5022f626ed36279915369c06fa6df0e76e</id>
<content type='text'>
systemd-sleep scans only /usr/lib/systemd/system-sleep/. The step created /etc/systemd/system-sleep/ and installed the hook there, so it never ran. Velox came out of about fifteen hibernate cycles since 08-21 with bluetooth rfkilled, and TLP's own resume hook carried the block forward every time. I dropped the mkdir, since the systemd package owns the real directory. The step's test now asserts the full install list, so a copy under /etc fails it.
</content>
</entry>
<entry>
<title>fix: declare libreoffice-fresh, imv and git-lfs</title>
<updated>2026-09-25T17:05:29+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-09-25T17:05:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=dec0446b7e990177edc34b071ba63c4942e867be'/>
<id>urn:sha1:dec0446b7e990177edc34b071ba63c4942e867be</id>
<content type='text'>
Each of the three backs something the dotfiles already ship, and each fails quietly rather than loudly when it's missing.

libreoffice-fresh is what the mimeapps.list defaults for presentations, documents and spreadsheets resolve to. With the package absent, xdg-mime doesn't error. It falls through to the next application claiming the type, which on a machine carrying the winvm dotfiles is powerpoint.desktop. Every .pptx opened a Windows VM for a month and the only symptom was that it felt slow.

imv is what gui-open --image execs. git-lfs is required by any repo tracking globs in LFS, which fails every checkout without it.

All three were installed before the 2026-08-13 rebuild and gone after it, because nothing in the installer declared them.

I made the test run supplemental_software with pacman_install stubbed as a recorder, asserting each package is invoked exactly once under both desktop environments. Running the function beats matching its source because only a run resolves the conditionals that could make "every machine installs this" false. A fourth assertion pins ranger present under dwm and absent under hyprland, so a harness that stopped resolving conditionals fails loudly instead of passing the other three vacuously.
</content>
</entry>
<entry>
<title>fix(install): mask passim when fwupd is installed</title>
<updated>2026-09-13T12:02:39+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-09-13T12:02:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=495d16d17b49d37336f1c1189543928b396449e0'/>
<id>urn:sha1:495d16d17b49d37336f1c1189543928b396449e0</id>
<content type='text'>
passim is fwupd's LAN metadata-sharing daemon and listens publicly on 0.0.0.0:27500. Any fwupdmgr run D-Bus-activates it. The unit is static, so disabling it is a no-op and it comes back on the next run. Masking is what holds. Every install gets it, not only laptops: the listener is public on any host, and ratio has run with it masked since July without fwupd missing it. Velox had only been disabled and got the mask on 2026-09-12.
</content>
</entry>
<entry>
<title>fix(install): stop enabling the WS-Discovery host daemon</title>
<updated>2026-09-13T12:02:39+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-09-13T12:02:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=64ccceff708535cba51e16c36cd77c14b6c8a729'/>
<id>urn:sha1:64ccceff708535cba51e16c36cd77c14b6c8a729</id>
<content type='text'>
wsdd.service advertises this machine as a Samba host to Windows clients. Nothing the installer sets up runs Samba, so it advertised a share server that doesn't exist while listening on every interface, VPN and tailscale links included. Browsing Windows shares is the other direction: gvfs-wsdd spawns its own wsdd in discovery mode, so the package stays and only the service goes. A re-run on a machine set up before this disables the unit. A fresh install has no unit yet and skips quietly.
</content>
</entry>
<entry>
<title>feat(install): default DNS over TLS off on the Proton tunnel links</title>
<updated>2026-09-13T12:02:39+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-09-13T12:02:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=20196051d9cd25d775373a48fcf05dc258497301'/>
<id>urn:sha1:20196051d9cd25d775373a48fcf05dc258497301</id>
<content type='text'>
The resolved drop-in pins DNSOverTLS=yes for every link. Proton VPN (proton0) and the static Proton WireGuard profiles (wgpvpn) push an in-tunnel resolver (10.2.0.1) that answers plain port 53 and never completes TLS on 853, so every lookup through the tunnel hung. The Proton client recreates its NetworkManager profile on each connect, so a per-profile setting can't stick.

NM pushes a [connection-tunnel-dot] default matched on those two interface names to resolved on every activation. Wifi and everything else keep the strict setting. Ratio and velox already carry the drop-in by hand. This makes a rebuild carry it too.
</content>
</entry>
<entry>
<title>fix(installer): clone my working repos with full history</title>
<updated>2026-08-20T07:15:19+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-20T07:15:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=9f3ab5d0e6aa8936bfffea6027e5882ce87108de'/>
<id>urn:sha1:9f3ab5d0e6aa8936bfffea6027e5882ce87108de</id>
<content type='text'>
archsetup and dotfiles were cloned with --depth 1. They aren't build trees. They're the two repos I develop in on every machine this installs, and velox came back from its rebuild carrying 7 commits of history in each instead of 851.

A shallow clone degrades quietly. Past the graft point `git log -- &lt;path&gt;` answers "no commits" rather than failing, so a search of history for specific files came back empty and exited clean. The clone couldn't see the history they live in. Blame and bisect break the same way, less dangerously.

Dropping --depth also drops the implicit --single-branch, so both clones now fetch every branch. That's what I want in a repo I work in.

The AUR build clones stay shallow. They exist to run make install and are then discarded. A test asserts they keep --depth 1, so a broad sed can't take them along.
</content>
</entry>
<entry>
<title>fix(installer): mask power-profiles-daemon so TLP survives on laptops</title>
<updated>2026-08-16T09:58:44+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-16T09:58:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=6dbc86df63a12b6ea16287bd1086b6aed545329b'/>
<id>urn:sha1:6dbc86df63a12b6ea16287bd1086b6aed545329b</id>
<content type='text'>
power-profiles-daemon.service declares Conflicts=tuned.service tlp.service auto-cpufreq.service, so systemd TERMs TLP the moment ppd starts. The line is in ppd's unit, not tlp's, so grepping tlp.service for it finds nothing.

Leaving ppd disabled was never enough. It ships D-Bus activation files, so the desktop-settings panel's own powerprofilesctl call starts it on demand. Velox ran that way from its rebuild on 2026-08-13 until today. TLP failed at every boot and none of its battery policy applied, while the machine looked correctly configured.

I mask and then stop. The mask closes the re-activation window, and the stop is what makes a repair re-run take effect, since a mask alone leaves a running ppd running.

I left desktops alone. They have no TLP to conflict with, and the panel's power control needs ppd there.
</content>
</entry>
</feed>
