<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/Makefile, 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-07-16T20:59:50+00:00</updated>
<entry>
<title>fix(test): stop silently skipping every integration test</title>
<updated>2026-07-16T20:59:50+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-16T20:59:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=f30a96edd320337ea9a35d2f0fc0cf21f94deb05'/>
<id>urn:sha1:f30a96edd320337ea9a35d2f0fc0cf21f94deb05</id>
<content type='text'>
INTEGRATION_TESTS globbed test-integration-%.el through $(wildcard ...), which
takes a shell glob where % is a literal character, not a pattern. It expanded to
nothing, so test-all skipped the integration phase and still printed "All tests
complete". Fourteen files never ran, for as long as the variable has existed.
The % is right one line up, because filter-out does take make patterns.

The glob is now test-integration-*.el, and the counts add up: 597 unit + 14
integration = the 611 test files on disk.

Turning the gate on surfaced five failures, none of them in production code.

Four were rotting fixtures. parse-ics drops events outside a rolling window of
today minus calendar-sync-past-months to plus future-months, and four tests fed
it dates pinned to November 2025 or February 2026. They passed when written and
began failing once the window slid past them. Their neighbours survived for two
reasons: some hand their fixture to parse-event, which applies no window, and
the weekly ones use unbounded RRULEs that keep generating into the window
however old the DTSTART is. The fixtures now build dates relative to now, which
is what the timezone file's own helper already did.

The fifth was a real regression, caught five months late. The recording toggle
test asserted on a fixture device and got whatever hardware is plugged into the
developer's machine. cj/recording-get-devices runs --validate-system-audio,
which shells to pactl, finds the fixture device isn't a real source, and
auto-fixes the configured device to the default sink's monitor. The test mocked
start-process-shell-command but not shell-command-to-string, so validation
reached the real machine. It passes at 5bdd3420~1 and fails at 5bdd3420, the
commit that added that validation in February.

I faked pactl at the shell boundary rather than stubbing --validate-system-audio
out, so the validation logic still runs, against a fixture machine.
</content>
</entry>
<entry>
<title>chore: archive resolved tasks older than a week</title>
<updated>2026-06-29T20:17:53+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-29T20:17:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=b46e1f02d9d5124aaccc927f4391c850626438df'/>
<id>urn:sha1:b46e1f02d9d5124aaccc927f4391c850626438df</id>
<content type='text'>
make task-sorted now ages the Resolved section. Tasks closed more than a
week ago, and any with no CLOSED date, move out to archive/task-archive.org,
keeping only the last week of closed tasks in todo.org. The target then runs
org-lint on todo.org to catch structural problems from the move. This pass
moved 207 tasks to the archive and pulled 4 newly-closed tasks into Resolved,
dropping todo.org from 9,600 to 5,600 lines.
</content>
</entry>
<entry>
<title>chore(ai): archive gptel and remove it from the live config</title>
<updated>2026-06-24T00:12:58+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T00:12:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=10fa6f4e2e7150ad99827721ada1ae4badcc5e90'/>
<id>urn:sha1:10fa6f4e2e7150ad99827721ada1ae4badcc5e90</id>
<content type='text'>
I archived gptel to archive/gptel/ since I rarely use it. Moved there: the six gptel modules (ai-config, ai-conversations, ai-conversations-browser, ai-mcp, ai-quick-ask, ai-rewrite), the gptel-tools/ directory, custom/gptel-prompts.el, their test files and utilities, and the four gptel-only specs.

Scrubbed from the live config: the ai-config require in init.el, which also drops the whole C-; a keymap; the gptel-mode emojify hook in font-config.el; the gptel-tools entries in the Makefile clean target and the coverage runner; and the gptel feature notes in README. Cancelled the open gptel tasks in todo.org (the AI Open Work issues, the feature-extension brainstorm, the velox gptel-magit bug).

ai-term stays. It is the ghostel Claude launcher, independent of gptel.

Verified: every module loads, a batch init launch reaches completion clean, and the full test suite shows only pre-existing coverage failures unrelated to this change.
</content>
</entry>
<entry>
<title>build: add task-sorted target to archive resolved todo tasks</title>
<updated>2026-06-16T04:46:33+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-16T04:46:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=549808155cc45ca12a66915c6a195b1c00d4618b'/>
<id>urn:sha1:549808155cc45ca12a66915c6a195b1c00d4618b</id>
<content type='text'>
make task-sorted wraps todo-cleanup.el --archive-done, moving DONE/CANCELLED level-2 subtrees from Open Work into Resolved. Ran it: archived this session's closed tasks.
</content>
</entry>
<entry>
<title>build: add deploy-wip target for live WIP theme reload</title>
<updated>2026-06-15T13:22:35+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-15T13:22:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=9b46e603c8c4efff773f71e1ecd1de793fd2c96a'/>
<id>urn:sha1:9b46e603c8c4efff773f71e1ecd1de793fd2c96a</id>
<content type='text'>
Build scripts/theme-studio/WIP.json into themes/WIP-theme.el, load it into the running daemon via the existing theme-reload target, and fire a silent desktop notification on success. The notify runs after the reload, so a build or load failure aborts before claiming the theme deployed.
</content>
</entry>
<entry>
<title>feat(theme-studio): make targets for the build-theme converter</title>
<updated>2026-06-14T23:20:04+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-14T23:20:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=fe75ac13b4082644b4ce9eeba7f49d3eea2cc716'/>
<id>urn:sha1:fe75ac13b4082644b4ce9eeba7f49d3eea2cc716</id>
<content type='text'>
theme-studio-theme converts a Theme Studio JSON export to themes/&lt;name&gt;-theme.el. theme-studio-theme-load disables the custom themes and loads one in the running Emacs. theme-studio-theme-reload chains the two. Each delegates to the scripts/theme-studio/Makefile and errors clearly when its required JSON or THEME argument is missing.
</content>
</entry>
<entry>
<title>build(theme-studio): expose every theme-studio target from the root</title>
<updated>2026-06-09T12:55:56+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-09T12:55:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=99977ae7cf961f30e3be09178ee652e744c846c3'/>
<id>urn:sha1:99977ae7cf961f30e3be09178ee652e744c846c3</id>
<content type='text'>
Only test and coverage delegated from the root; check, gen, and open were local-only, so `make theme-studio-open` didn't exist. Added the missing delegations so the whole family is reachable from the root with the theme-studio- prefix, matching the convention. gen and open forward SEED through to the sub-make for viewing a specific palette. Grouped them under their own heading in `make help`.
</content>
</entry>
<entry>
<title>build(theme-studio): add a local Makefile; root delegates test + coverage</title>
<updated>2026-06-09T12:53:12+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-09T12:53:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=3d7cc92a1d845caa845c5af0ef586694bdc40556'/>
<id>urn:sha1:3d7cc92a1d845caa845c5af0ef586694bdc40556</id>
<content type='text'>
theme-studio is a self-contained Python + JS subproject with its own toolchain (python3, node, uvx, headless Chrome), unrelated to the root Makefile's Elisp/ERT world. Gave it a local Makefile that owns that toolchain — test, check (fast, no browser), coverage, gen, open — so the build logic lives with the code and the short target names don't collide with the root's Elisp-flavored test/coverage.

The root keeps the discoverable entry points: theme-studio-test and a new theme-studio-coverage now delegate via make -C. run-tests.sh grows a --no-browser flag so `make check` can skip the headless-Chrome gates for a fast inner loop. gen/open take an optional SEED to view a specific palette.

coverage reports both halves: node --experimental-test-coverage for the three JS modules (all 100% line, ~96% branch) and uvx coverage for generate.py (89% lines; the rest is the __main__ writer and the optional seed-env branch).
</content>
</entry>
<entry>
<title>test(theme-studio): add a one-command test runner and make target</title>
<updated>2026-06-09T03:09:13+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-09T03:09:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=27a089f3607c0d78419b681b9d7d7422d3afac00'/>
<id>urn:sha1:27a089f3607c0d78419b681b9d7d7422d3afac00</id>
<content type='text'>
The browser hash gates were run by hand through headless Chrome, so a picker-JS regression only surfaced if someone remembered to run them. run-tests.sh now drives the whole pyramid in one command: regenerate the page, the Python templating tests, the Node unit tests plus inline-integrity, a syntax check of the spliced page script, and the six browser hash gates. It exits non-zero on any failure, and make theme-studio-test calls it.

The browser gates need a Chromium-family browser. When none is found they report SKIPPED rather than passing, so a machine without Chrome can't turn the gates silently green.
</content>
</entry>
<entry>
<title>build: add compile-file for single-file byte-compile with the project load path</title>
<updated>2026-05-25T19:58:36+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-25T19:58:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=a3a399b862eabfcbfe37a91f9445640cd28e4b3c'/>
<id>urn:sha1:a3a399b862eabfcbfe37a91f9445640cd28e4b3c</id>
<content type='text'>
Bare emacs -Q --batch byte-compile-file fails on local compile-time requires (undead-buffers for a module, dupre-palette for a theme file) because nothing is on the load path, even though init and the test harness load fine. I added a compile-file target that compiles one file with the project load path (modules, themes, tests, plus package-initialize), and put themes on make compile's path too.

Bare emacs -Q stays unsupported by design; compile-file is the documented command, and it guards against a missing FILE. Verified modules/dashboard-config.el and themes/dupre-faces.el both compile through it.
</content>
</entry>
</feed>
