<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/docs/design, 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-08-25T12:30:04+00:00</updated>
<entry>
<title>fix(telega): build the server image locally to meet tdlib 1.8.66</title>
<updated>2026-08-25T12:30:04+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-25T12:30:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=91fbac722e83cd108a295542a3c88de66d209fe8'/>
<id>urn:sha1:91fbac722e83cd108a295542a3c88de66d209fe8</id>
<content type='text'>
MELPA's 2026-08-18 telega raised telega-tdlib-min-version to 1.8.66. The pinned upstream image ships 1.8.64, so telega killed its own server on every launch. Upstream's only 1.8.66 image won't start: it's missing libglycin (zevlg/telega.el#596).

docker/telega-server/Dockerfile derives from that upstream image, pinned by digest, and adds the one missing package. make telega-image builds it as cj/telega-server:1.8.66-glycin, cj/telega-docker-image defaults to that tag, and a test holds the two equal. cj/telega now refuses to launch with a make telega-image hint when the image isn't built, since docker would otherwise try to pull a local-only tag from the registry. setup-telega.sh points at the make target instead of M-x telega-server-build.

I chose the local build over pinning the telega package back to 20260706.2147. The derived image satisfies both machines' floors. package.el can't pin a version and MELPA serves only its latest build, so nothing would enforce the package pin. When #596 is fixed upstream the pin returns to a registry digest and the Dockerfile goes.
</content>
</entry>
<entry>
<title>docs: record the telega docker pin and tdlib version mismatch</title>
<updated>2026-08-25T00:43:05+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-25T00:43:05+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=ac1d034d09dd37305e84d08438fef268ed8173bc'/>
<id>urn:sha1:ac1d034d09dd37305e84d08438fef268ed8173bc</id>
<content type='text'>
MELPA's 2026-08-18 telega build raised telega-tdlib-min-version to 1.8.66. The pinned zevlg/telega-server image ships 1.8.64, so telega kills its own server on every launch and nothing reports it.

The note carries the measurements and why the armed death alert wasn't seen, which is still unmeasured. It also records why zevlg/telega-server:latest isn't a fix (zevlg/telega.el#596: missing libglycin), the derived image I verified, and the pinning decision I haven't made yet.
</content>
</entry>
<entry>
<title>docs: record how the ambience audio was built</title>
<updated>2026-08-06T16:50:47+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-08-06T16:50:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=36c737f45efc4f9459a7923d62ccf2cf5bf2686a'/>
<id>urn:sha1:36c737f45efc4f9459a7923d62ccf2cf5bf2686a</id>
<content type='text'>
- Keeps the stream-copy loop technique and its measurements.
- Notes the amix normalize=0 trap that silently discards the mix ratio.
- Records the loop-period arithmetic behind the crossfade.
- Explains why the openly-licensed set sounds better but its rain is wrong.

The audio itself stays untracked.

Claude-Session: https://claude.ai/code/session_01WpQhUr9mNrXss3HiaN6G2s
</content>
</entry>
<entry>
<title>fix(flycheck): lint ledger buffers, which nothing ever did</title>
<updated>2026-07-10T06:23:31+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-10T06:23:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=55b85754d78f268907ad5fa5be886973bbef921d'/>
<id>urn:sha1:55b85754d78f268907ad5fa5be886973bbef921d</id>
<content type='text'>
flycheck-ledger registers a ledger checker, but a checker only runs where flycheck-mode is on, and flycheck-mode was hooked to sh-mode and emacs-lisp-mode only. There's no global-flycheck-mode. So an unbalanced transaction in a financial file produced no warning at all, while the ledger module's commentary advertised linting.

The hook goes in flycheck-config, not ledger-config, so that list stays the one answer to "where is flycheck turned on?".

Verified on an unbalanced fixture: flycheck now reports "Transaction does not balance" with the $10.00 remainder, on the right line.

I also accepted the whole-buffer sort the audit flagged. ledger-sort-startkey keys on the ISO date alone, and sort-subr is stable, so a save orders by date and leaves same-day transactions where they were typed. The audit note records both.
</content>
</entry>
<entry>
<title>test(ledger): audit ledger-config and pin its current behavior</title>
<updated>2026-07-10T05:44:39+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-10T05:44:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=621287447f149eb571e00c067e410704c4ebf968'/>
<id>urn:sha1:621287447f149eb571e00c067e410704c4ebf968</id>
<content type='text'>
The linting doesn't run. flycheck-ledger loads and registers the ledger checker, but flycheck-mode is hooked to sh-mode and emacs-lisp-mode only, and there's no global-flycheck-mode. I checked a live ledger-mode buffer: checker registered, flycheck-mode nil. Unbalanced transactions and typo'd account names produce no warning, on a financial file, while the module commentary claims linting.

Three smaller findings. Every save reorders the whole file, because ledger-mode-clean-buffer calls ledger-sort-buffer over point-min to point-max. The demoted error around it lets a save proceed after a partial rewrite, with nothing to roll back. Reconcile has no confirmation and clears whole transactions.

Five characterization tests pin what exists now, including the clean-on-save default the audit questions. I fixed nothing: the guardrail choices are a separate task, and only the flycheck gap is a defect rather than a preference.
</content>
</entry>
<entry>
<title>docs(design): survey where a curated "?" help menu fits</title>
<updated>2026-07-10T05:38:21+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-10T05:38:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=02c2e0ee8e00869681595bd7b80a98219563b39f'/>
<id>urn:sha1:02c2e0ee8e00869681595bd7b80a98219563b39f</id>
<content type='text'>
The mechanical half of the "?" convention task. I probed ten modes from their live keymaps rather than from source, because a package's define-key calls don't always agree with what lands in the map.

Four modes have both ? and H free, so nov, eat, and the two elfeed modes can adopt the convention without displacing anything. Three bind ? to something small that adopting it would displace. mu4e-headers is the one real conflict: its ? marks mail unread, a state-mutating command in the marking family.

magit already binds ? to its own dispatch. The convention isn't new, it's magit's habit generalized.

I ran the probe in a throwaway batch Emacs rather than the daemon, since probing calibredb and mu4e in a live session would force-load them. mu4e isn't an ELPA package and needed its site-lisp path.
</content>
</entry>
<entry>
<title>docs(design): map Org module ownership and load boundaries</title>
<updated>2026-07-10T05:35:28+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-10T05:35:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=7f9c44023a89ef47a3a1a76a2ada4d69ba0ad678'/>
<id>urn:sha1:7f9c44023a89ef47a3a1a76a2ada4d69ba0ad678</id>
<content type='text'>
Sixteen modules make up the Org workflow, and nothing wrote down which owns what. Answering "who sets this variable?" meant grepping. The note maps each module to its behavior, the shared variables with more than one writer, and the init.el load order.

The load-boundary facts are the useful part. Four modules append to org-capture-templates, four touch org-agenda-files, and five register org-protocol handlers. quick-video-capture loads twenty-four lines before org-config because it's grouped with the media modules. Every Org module loads eagerly, including the five its own headers call optional.

I recorded four follow-ups in the note instead of fixing them: a tracked .bak file under modules/, a missing header on the agenda debug module, no collision check on org-protocol handlers, and that eager loading.
</content>
</entry>
<entry>
<title>docs: reclassify subr-mock-migration as a design note</title>
<updated>2026-07-04T22:19:06+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-04T22:19:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=48f0bbd7a1894fafd46f1093d5a17300efbba0bb'/>
<id>urn:sha1:48f0bbd7a1894fafd46f1093d5a17300efbba0bb</id>
<content type='text'>
</content>
</entry>
<entry>
<title>docs(specs): adopt status-heading lifecycle convention across specs</title>
<updated>2026-07-04T20:38:00+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-04T20:38:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=38200c6683e55860b044568cd70004dcbc7c4031'/>
<id>urn:sha1:38200c6683e55860b044568cd70004dcbc7c4031</id>
<content type='text'>
Migrate 29 legacy specs off the old shape (a status suffix in the filename plus a :STATUS: property drawer) onto the docs-lifecycle status heading: a top-level heading carrying the org lifecycle keyword and a dated history line, with the two #+TODO sequences in the header.

Dropping the -doing/-implemented/-superseded suffixes means a status change no longer forces a rename and link surgery. Each keyword comes from the spec's own recorded status. The four specs already on the heading form are untouched, and every inbound reference now points at the new names.

The status board is one grep: rg '^\* (DRAFT|READY|DOING|IMPLEMENTED|SUPERSEDED|CANCELLED) ' docs/specs/
</content>
</entry>
<entry>
<title>docs: sort three theme-studio specs into docs/specs with status headings</title>
<updated>2026-07-02T05:07:33+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-02T05:07:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=67e767466ba63e6e673e4157b68d58948a493462'/>
<id>urn:sha1:67e767466ba63e6e673e4157b68d58948a493462</id>
<content type='text'>
First spec-sort pass under the docs-lifecycle convention: color-families -&gt; READY (its status field carried the 2026-06-10 confirmation), palette-columns and palette-ramps -&gt; DRAFT. Each got the authoritative status heading with an :ID: UUID; six inbound links rewritten. subr-mock-migration-spec is -spec-named but lacks the spec spine, so it stays put until it's renamed or retrofitted.
</content>
</entry>
</feed>
