<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs, branch main</title>
<subtitle>My Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/dotemacs/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/'/>
<updated>2026-10-07T14:20:57+00:00</updated>
<entry>
<title>chore: ignore the Emacs 31 network-security.eld store</title>
<updated>2026-10-07T14:20:57+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-10-07T14:20:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=8d4b3d226f5a8990cae7b3fe74deda6b5fd2c127'/>
<id>urn:sha1:8d4b3d226f5a8990cae7b3fe74deda6b5fd2c127</id>
<content type='text'>
Emacs 31 renamed the Network Security Manager store from network-security.data to network-security.eld, so the new file showed up untracked at the repo root. I ignore both names so a pre-31 checkout stays clean too.
</content>
</entry>
<entry>
<title>fix(elfeed): load bytecomp before elfeed can load</title>
<updated>2026-10-05T10:12:26+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-10-05T10:12:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=2a1c6b3dade091e6486d90aa6518d888492e7e1a'/>
<id>urn:sha1:2a1c6b3dade091e6486d90aa6518d888492e7e1a</id>
<content type='text'>
- elfeed.el reads byte-compile-root-dir as it finishes loading.
- That variable exists only once bytecomp is loaded.
- Without it, requiring elfeed signals void-variable.
- The live config loads bytecomp through use-package first.
- make test doesn't, so the elfeed helper tests failed.
- I require bytecomp in elfeed-config ahead of any elfeed load.
</content>
</entry>
<entry>
<title>fix(make): keep elpa bytecode out of clean-compiled</title>
<updated>2026-10-05T10:12:26+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-10-05T10:12:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=cbd156907033c6164a1f12fdab917a1d65381893'/>
<id>urn:sha1:cbd156907033c6164a1f12fdab917a1d65381893</id>
<content type='text'>
- clean-compiled deleted every .elc in the tree, elpa included.
- make clean runs it, so each clean wiped package bytecode.
- Nothing here rebuilds it, so packages loaded from source.
- Source loads skip native-comp JIT and slow startup.
- Emacs 31 also warns per cookie-less file loaded from source.
- I made the find skip elpa/ and quote its start point.
- New tests run the real target against a throwaway home.
- A dry run must show the temp path first.
</content>
</entry>
<entry>
<title>fix(dirvish): move the sidebar to F9 so F11 toggles fullscreen again</title>
<updated>2026-09-22T18:29:33+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-09-22T18:29:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=7c9f92eb0a6751d04a43ffe3cc5f725fce5ab371'/>
<id>urn:sha1:7c9f92eb0a6751d04a43ffe3cc5f725fce5ab371</id>
<content type='text'>
Stock Emacs binds F11 to toggle-frame-fullscreen, the key every other application uses for it. This config never rebound it, but dirvish-config's :bind put dirvish-side on F11 and shadowed the stock binding. I moved the sidebar toggle to F9, the free bare F-key: ai-term left it for M-SPC in June and the recording chord came off it today. F2 is the preview key and F5 is reserved for the debug backend, so neither was a candidate.

The org-capture F-key guard follows the command rather than the key. F9 joins its list and F11 leaves it, since a fullscreen toggle pops nothing over a capture. The tests pin the new key, the un-shadowed F11, and the guard change.
</content>
</entry>
<entry>
<title>feat(transcription): add the self-hosted ratio backend</title>
<updated>2026-09-22T17:50:04+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-09-22T17:50:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=befb206ae7b2daeb61acd20f11aa9d2d5017733f'/>
<id>urn:sha1:befb206ae7b2daeb61acd20f11aa9d2d5017733f</id>
<content type='text'>
scripts/ratio-transcribe runs whisper plus speaker diarization on my own transcription host over an ssh job queue, with a local worker as the fallback when the host is unreachable. It needs no API key, so its descriptor carries nil for the auth host and the env var. The process environment passes through untouched. SPEAKERS=N in the environment pins the diarizer's speaker count.

The interactive switcher used to carry its own copy of the backend list, so a backend added to the descriptors was reachable only by setq. It now derives its choices from the descriptor alist, and a test pins the two to each other.

The script's own behavior (argument validation, the job-id hash, the remote and local branches) is tested in the repo it came from. A bats mirror of those cases is tracked separately.
</content>
</entry>
<entry>
<title>fix(recording): drop the F9 and S-F9 recording chords</title>
<updated>2026-09-22T17:50:04+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-09-22T17:50:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=44a7e4284a7dbd660c978158ae8419ea61f4550c'/>
<id>urn:sha1:44a7e4284a7dbd660c978158ae8419ea61f4550c</id>
<content type='text'>
With Fn Lock on the Framework 13 the F-key row sends plain function keys, so a bare F9 press started a screen recording. I removed both chords rather than just F9. The module treated the pair as one feature, and a lone S-F9 audio chord on a live F-key row is one grazed key from an unwanted recording. The C-; r prefix is now the only way to reach the toggles.

The removal covers the global map and the four EAT keymaps that carried the chord so char mode couldn't swallow it. In a char-mode buffer F9 reaches the program under the cursor again. The tests pin that, with F8 as the control that the fixture is real.
</content>
</entry>
<entry>
<title>test: repair the seven files red under Emacs 31.1</title>
<updated>2026-08-26T18:25:39+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-26T18:25:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=474a9bed31c583761e55b6072f07fcfd6d095471'/>
<id>urn:sha1:474a9bed31c583761e55b6072f07fcfd6d095471</id>
<content type='text'>
None of the seven was a config regression. Each file had its own cause:

- config-utilities: the tests mocked fboundp with cl-letf. fset on a subr autoloads comp-run, which requires bytecomp, whose defun of byte-compile-file replaced the mock installed earlier in the same cl-letf. 30.2 hid it because ert happened to load bytecomp first. I extracted cj/--compile-elisp-file with an injectable availability predicate (fboundp by default), made cj/compile-this-elisp-buffer the wrapper, and had the tests inject a predicate instead of redefining a primitive. Added the missing no-compiler case.
- system-defaults-functions: the file let-bound use-package-always-ensure before anything declared it special. 30.2 downgraded that to a "Failed to parse package recentf" warning; 31.1 moves the defcustom to autoload time, where it is fatal at load. One defvar before the let.
- calibredb-epub-config: the jump tests stubbed calibredb while it was still an autoload, so the module's require loaded the real definition over the stub and the real command always ran. Require calibredb before any stub.
- agenda-query--render: org 9.8.7 parses the priority cookie with (looking-at org-priority-regexp), whose lazy prefix swallows everything between the stars and the cookie. The fixture now has no cookie and pins that the keyword is not recognised.
- prog-general-yas-activation: python-ts-mode prompts to install a missing grammar, which a batch run cannot answer. The test skips on treesit-ready-p rather than on the mode existing, and the module comment says why.
- integration-recurring-events: the fixtures are America/Chicago and the assertions expect Chicago rendering, so the file only passed on a machine in Central time. TZ is pinned in setup and restored in teardown.

The integration failure had been invisible since 08-17 because make test stops after a red unit phase. make test exits 0 again for the first time since then.
</content>
</entry>
<entry>
<title>chore(hooks): anchor the sk- secret pattern on a word boundary</title>
<updated>2026-08-26T18:21:30+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-26T18:21:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=adff1ee51c7fcb32872ce7b2f39ed35c1daa5ed0'/>
<id>urn:sha1:adff1ee51c7fcb32872ce7b2f39ed35c1daa5ed0</id>
<content type='text'>
Unanchored, sk- followed by twenty word characters matched inside any hyphenated identifier ending in sk- (task-, risk-, disk-), which blocked a commit on an assertion naming task-missing-last-reviewed. A real key always starts its token. This brings the hook back in line with the language bundle's copy.
</content>
</entry>
<entry>
<title>fix(init): declare malyon and 2048-game so a fresh machine installs them</title>
<updated>2026-08-26T18:21:29+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-26T18:21:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=0afff24b6e0e80bc5b83ab233ada822caef728a6'/>
<id>urn:sha1:0afff24b6e0e80bc5b83ab233ada822caef728a6</id>
<content type='text'>
a8571eff moved games-config behind with-eval-after-load 'malyon and deleted the two use-package forms, which were the only thing that ever installed malyon and 2048-game. The old elpa directories masked that until the 2026-08-13 reinstall rebuilt elpa from declarations and both packages came up absent. I declared them in init.el's entertainment section with :defer t and :commands, so use-package-always-ensure installs them while the module stays command-loaded. They live in init.el rather than games-config because that module only loads once malyon has, so it can't be what installs malyon.

The new test checks that init.el declares both packages in forms use-package would install, and rejects :ensure nil and :load-path forms.
</content>
</entry>
<entry>
<title>fix(startup): keep the native-comp log alive so the compile queue drains</title>
<updated>2026-08-26T18:05:37+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-26T18:05:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=9b102d6fb23074bebc626bfe4e61c677c006ae37'/>
<id>urn:sha1:9b102d6fb23074bebc626bfe4e61c677c006ae37</id>
<content type='text'>
comp-run parks every async native-compile worker on *Async-native-compile-log* and each worker's sentinel reads that buffer back before it starts the next job. The startup sweep in cj/dashboard-only killed the buffer, and killing a buffer SIGHUPs every :noquery process under it. Each sentinel then died with "Selecting deleted buffer" and comp--run-async-workers never ran again. The queue sat stranded for the life of the daemon and nothing it had queued was ever cached. The 31.1 upgrade emptied the eln cache. After that every boot queued about 240 files and spawned eight compilers at the moment of the first frame, then killed them, so the next boot did it all again. That storm on a cold boot is what sat behind the grey window before the dashboard.

I added the buffer to cj/undead-buffer-list so the sweep buries it, the same choice *Warnings* got in 63831060. The "Selecting deleted buffer" errors I filed in June as an async race were this.

The new tests pin the name to comp-async-buffer-name and run the sweep with a live :noquery process parked on the buffer. The process survives, while the same process on an ordinary buffer dies with it.
</content>
</entry>
</feed>
