aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-15 23:01:23 -0500
committerCraig Jennings <c@cjennings.net>2026-06-15 23:01:23 -0500
commit5b83e9a224115ecc86332db8c14104e7b0864bef (patch)
tree20e6e3133285923bb6fef85b5c012b263fb25664
parent8c8c05d219fdc91bb407c6bb239f8983d9573b1d (diff)
downloaddotemacs-5b83e9a224115ecc86332db8c14104e7b0864bef.tar.gz
dotemacs-5b83e9a224115ecc86332db8c14104e7b0864bef.zip
chore(todo): fix doubled :next: tag on music extract-faces
-rw-r--r--todo.org145
1 files changed, 58 insertions, 87 deletions
diff --git a/todo.org b/todo.org
index eecdc4ac5..2a40e2ba6 100644
--- a/todo.org
+++ b/todo.org
@@ -44,14 +44,6 @@ Tags are additive. For example, a small wrong-behavior fix can be
=:bug:quick:=, and a feature that requires internal restructuring can be
=:feature:refactor:=.
* Emacs Open Work
-** TODO [#C] theme-studio: alphabetize the assignment view list below the package divider :feature:quick:solo:studio:
-Sort the assignment view list alphabetically anywhere below the divider for the package views. From the roam inbox 2026-06-15.
-** TODO [#C] theme-studio: calibre package doesn't color properly :bug:studio:
-The calibre package preview has no elements to theme in the search list, and coloring switches to the string color on mismatched quotes. Investigate, then record a diagnosis and solution in this task before fixing. From the roam inbox 2026-06-15.
-** TODO [#C] music: extract faces for music config :refactor:quick:solo:next:
-Pull the music-config faces out to the theme (the config no longer defines faces directly): playlist name, status (paused, etc.), two mode colors per "button" (on vs off), a per-key symbol+text color, and a color for all other labels. Pairs with the 2026-06-14 face-stripping work (music-config faces were removed there and are currently undefined until the theme defines them). From the roam inbox 2026-06-15.
-** TODO [#C] music: show song information in the modeline :feature:
-Show basic song information in the modeline, with streaming-source support too. Write a spec for this one first. From the roam inbox 2026-06-15.
** TODO [#A] theme-studio: deploy-wip button on the browser page :feature:studio:next:
Add a button on the theme-studio page that runs the make deploy-wip target locally (build WIP.json into the theme, live-reload the daemon). The page is served from file://, so the browser can't run make directly. Needs a local bridge: a tiny localhost helper the button POSTs to, or a watched trigger file the page writes. Pick the mechanism before building. From the roam inbox 2026-06-15.
** TODO [#A] theme-studio: cannot reassign fg color :bug:studio:next:
@@ -65,7 +57,7 @@ RFC 5545 conformance holes in =modules/calendar-sync.el=, all agenda-visible (fr
- =:578= — comma-separated EXDATE lists (Google emits them) never parse; the exclusion drops silently and cancelled occurrences reappear on the agenda. Split on "," before parsing; no comma-case test exists.
- =:902= — timed events without DTEND render as all-day (time lost); multi-day all-day spans collapse to one day (end date unused, exclusive-DTEND unhandled). Emit start-time-only stamps and org date ranges.
-** TODO [#A] Calibre Open Work
+** TODO [#C] Calibre Open Work
:PROPERTIES:
:LAST_REVIEWED: 2026-06-06
:END:
@@ -107,30 +99,30 @@ Implemented 2026-06-06 in =modules/calibredb-epub-config.el=:
*** TODO Embed Calibre DB metadata into the EPUB files
Surfaced 2026-06-06 while building the bookmark naming: the metadata embedded in the EPUB files' OPF is worse than Calibre's database metadata. nov reads the embedded OPF and got truncated titles ("Frege" vs the filename's "Frege: A Guide for the Perplexed"), author-sort "Last, First" forms ("Christie, Agatha"), and lost punctuation ("A.B.C." -> "A B C"). The filenames (from Calibre's curated DB) are the good copy. Fix on the Calibre side: select all (or by library), run "Edit metadata -> Embed metadata into book files" so the DB metadata is written into each EPUB's OPF. Consider auditing author vs author_sort first. After embedding, the in-file metadata matches the library and any tool reading the files (nov, other readers, re-imports) gets the good data. Not an Emacs task; Calibre-side bulk maintenance.
-** DOING [#A] Lock screen silently fails — slock is X11-only :bug:quick:
+** DOING [#C] Lock screen silently fails — slock is X11-only :bug:quick:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-13
:END:
=modules/system-commands.el:105= binds the lockscreen command to =slock=, which can't grab a Wayland session; =cj/system-cmd= launches it detached with output silenced, so C-; ! l does nothing and the screen never locks. Security issue: Craig believes the screen locks when it doesn't. Fix: =hyprlock= (or =swaylock=), ideally resolved per session type via =env-wayland-p= so an X11 fallback survives for other machines. From the 2026-06 config audit.
Fixed 2026-06-13: lockscreen-cmd resolves to =loginctl lock-session= on Wayland (logind Lock → hypridle → hyprlock, the path idle/sleep locking already uses), =slock= on X11; also added the missing =(require 'host-environment)=. Live in the daemon; manual lock test under the Manual testing parent.
-** DOING [#A] mu4e: cmail can't trash, no account can refile :bug:quick:solo:
+** DOING [#B] mu4e: cmail can't trash, no account can refile :bug:quick:solo:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-13
:END:
=modules/mail-config.el:217-220= — the cmail context (primary account) sets only drafts/sent, so D falls back to default "/trash" which doesn't exist under ~/.mail (=/cmail/Trash= does); and NO context sets =mu4e-refile-folder=, so r targets nonexistent "/archive" everywhere. Accepting mu4e's offer to create the maildir strands mail in a directory mbsync never syncs — messages silently vanish from the server's view. Add =mu4e-trash-folder= to cmail + per-context =mu4e-refile-folder=. From the 2026-06 config audit.
Fixed 2026-06-13: cmail gets =mu4e-trash-folder= "/cmail/Trash"; refile is a per-message function (=cj/mu4e--refile-folder=) instead of a per-context string — mu4e context :vars are sticky, so a per-context refile leaks one account's archive folder into another. cmail → "/cmail/Archive"; gmail/dmail signal a =user-error= rather than move mail into an unsynced phantom folder (Craig chose the fail-safe over syncing [Gmail]/All Mail — the All Mail option means a multi-GB pull + cross-folder duplicates; revisit if local Gmail archiving is wanted). Applies on next mu4e open; pure dispatch helper covered by tests.
-** TODO [#A] Native compilation disabled config-wide; GC at stock 800KB :bug:
+** TODO [#A] Native compilation disabled config-wide; GC at stock 800KB :bug:next:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-13
:END:
From the 2026-06 config audit (verified against the live daemon). =early-init.el:69= =(setq native-comp-deferred-compilation nil)= — the obsolete alias of =native-comp-jit-compilation= — turns JIT native compilation OFF entirely, not "synchronous" as the comment claims: 19 .eln files exist for 184 packages, ~100 of 121 modules run interpreted for the daemon's lifetime, and system-defaults.el:42-44's speed-3/8-jobs/always-compile settings are dead. Plus =early-init.el:113-116= restores =gc-cons-threshold= to the captured STOCK default (800000, verified) post-startup — frequent small GC pauses forever. Together these plausibly feed the filed org-capture 15-20s task more than anything in the capture path itself. Actions: retest the old "Selecting deleted buffer" race on 30.2 and re-enable JIT (or AOT sweep); set a deliberate 16-64MB threshold (or gcmh). Check both before burning time on the capture-perf debug task.
-** TODO [#B] theme-studio: sort newest colors near the top :feature:studio:
+** TODO [#B] theme-studio: sort newest colors near the top :feature:studio:next:
Newly added colors currently land after the ground layer (bg/fg), low in the order. Surface them near the first entry instead, in both the palette color list and the gallery/dropdown, since the most recently added colors are usually the ones being worked on. From the roam inbox 2026-06-15.
-** TODO [#B] emacs: tag tasks by module name for sorting :refactor:studio:
+** TODO [#C] emacs: tag tasks by module name for sorting :refactor:studio:
Replace topic tagging with single-word module tags: :studio: for everything under scripts/theme-studio/, module-named tags elsewhere, :multi: for cross-area work. Drop bug/enhancement-style tags since work should be chosen on other bases. This changes the current six-tag convention, so update the priority-scheme section to document it, rewrite the task-audit workflow to reconcile tasks against the module scheme, then run the audit. Queue for end of session. From the roam inbox.
-** TODO [#B] 2026-06 full config audit — findings backlog :refactor:
+** TODO [#C] 2026-06 full config audit — findings backlog :refactor:
Module-by-module review of all 121 modules + init/early-init, holistic passes (startup/perf, stability, UX consistency, package strategy), and spin-offs into pearl, chime, emacs-wttrin. Method: parallel read-only review agents per module group; key claims spot-verified (incl. against the live daemon) before filing. Run 2026-06-11/12, COMPLETE. Tally: ~165 module findings + ~40 holistic + 30 spin-off ≈ 235 total; 40 high-impact bugs filed as standalone tasks above this parent; the rest live in the group children below. Spin-off findings delivered as inbox handoffs to pearl, chime, and emacs-wttrin (2026-06-12-0057). Start with the synthesis child below for the recommended attack order.
*** Synthesis: the overall picture and attack order
@@ -361,7 +353,7 @@ From the 2026-06 config audit, =modules/org-agenda-config.el=:
- =:182-191= — commentary and docstrings promise org-roam nodes tagged "Project" as agenda sources, but =cj/--org-agenda-scan-files= never scans them, and files added by the roam finalize-hook are wiped on the next =cj/build-org-agenda-list= cache rebuild (≤1h). Add a roam Project pass (mirror =org-refile-config.el:101-109=) or correct the docs.
- =:186,456= — agenda file list built unconditionally (inbox/calendars may not exist on a fresh machine) and =org-agenda-skip-unavailable-files= is unset — the exact interactive-prompt class that once hung the chime daemon. Filter with =file-exists-p= + set the var as backstop.
-** TODO [#B] ai-conversations: dead-buffer load, role flattening, non-atomic writes :bug:solo:
+** TODO [#C] ai-conversations: dead-buffer load, role flattening, non-atomic writes :bug:solo:
From the 2026-06 config audit, =modules/ai-conversations.el=:
- =:324= — load in a fresh session does =get-buffer-create "*AI-Assistant*"= (plain fundamental-mode buffer); =--ensure-ai-buffer= then sees it exists and never calls =(gptel)=. Sending doesn't work, autosave self-cancels (requires gptel-mode). Use =get-buffer= for the check; let ensure create. The browser RET/l path inherits this.
- =:240= — persistence drops gptel's =response= text properties, so a reloaded history replays to the model as ONE user message (model re-reads its own answers as Craig's words). Adopt gptel's native bounds persistence or re-mark on load from the "* Backend:" headings.
@@ -702,16 +694,16 @@ Expected outcome:
** TODO [#B] Auto-dim: org headings, links, and tags do not dim in unfocused windows :bug:
auto-dim-other-buffers-affected-faces (auto-dim-config.el) remaps font-lock and a few org faces to the flat dim face, but not org-level-1..8, org-link, or org-tag, so headings, links (seen in daily-prep.org), and tags like :solo: stay lit when the window loses focus. Decide the dim approach: a flat-dim remap like font-lock (quick) versus dedicated -dim variants surfaced through org-faces / theme-studio (richer, matches the keyword work; Craig flagged org-tags may want the org-faces treatment). Consolidates three roam-inbox captures.
-** TODO [#B] calendar-sync robustness: atomic writes, curl --fail, zero-event false errors :bug:solo:
+** TODO [#B] calendar-sync robustness: atomic writes, curl --fail, zero-event false errors :bug:solo:next:
From the 2026-06 config audit, =modules/calendar-sync.el=:
- =:1309= — agenda file written via =with-temp-file= directly on the target (truncate-in-place); org-agenda/chime reading mid-write sees a partial calendar, hourly. Write temp + =rename-file= (atomic same-fs). Same for =--save-state= :258.
- =:1284= — curl runs without =--fail=: an HTTP 404/500 error page exits 0 and the HTML proceeds into conversion.
- =:1229-1233= — =--parse-ics= returns nil for both garbage and a valid calendar with zero in-window events, so healthy near-empty calendars report "parse failed" in =calendar-sync-status=. Distinguish the cases.
-** TODO [#B] cj/gptel-switch-backend reintroduces the string-model crash :bug:quick:solo:
+** TODO [#C] cj/gptel-switch-backend reintroduces the string-model crash :bug:quick:solo:
=modules/ai-config.el:272= — =(setq gptel-model model)= with the raw completing-read STRING — the documented wrong-type-argument-symbolp modeline hang (CLAUDE.md gotcha), reachable from C-; a B today. =cj/gptel-change-model= (C-; a m) already does backend+model switching and interns correctly. Intern here, or delete switch-backend and keep one command. From the 2026-06 config audit.
-** DOING [#B] C-s C-s vertico-repeat path never works :bug:quick:solo:
+** DOING [#B] C-s C-s vertico-repeat path never works :bug:quick:solo:next:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-13
:END:
@@ -724,7 +716,7 @@ From the calibredb keybindings work 2026-06-06. The pattern that worked: in a mo
Task: survey the modes/modules Craig works in and identify where a =?= -> curated-help-menu (transient) makes sense. Candidates: any major-mode buffer with single-key bindings and no good discovery affordance -- calibredb (done), nov, dirvish, mu4e, ghostel/term, signel, pearl/linear, ELFeed, etc. For each, note whether =?= is free or already a help dispatch, and whether a curated menu (vs the package's own) adds value. Establish it as a convention (and maybe a small helper/macro to define a curated =?= menu consistently).
-** TODO [#B] dirvish M (mark all files) marks every other file :bug:quick:solo:
+** TODO [#B] dirvish M (mark all files) marks every other file :bug:quick:solo:next:
=modules/dirvish-config.el:218= — =dired-mark= advances point to the next line itself; the loop's extra =forward-line 1= then skips it, so consecutive files are marked alternately. Live mis-marking on a key that feeds batch operations (delete/copy on marked files) — data-loss adjacent. Drop the manual forward-line when a mark was made (or =dired-unmark-all-marks= + mark dirs + =dired-toggle-marks=). The trivial line-predicate helper is tested; the loop isn't — add the marked-count test. From the 2026-06 config audit.
** TODO [#B] Dupre diff-changed / diff-refine-changed legibility :bug:
@@ -1278,7 +1270,7 @@ Add the buffer-local var, set it on each "Run a test..." selection, use it as th
*** TODO [#B] TS/JS coverage status sync
Update the =dev-fkeys.el= header comment (L33) — TS/JS is no longer punted; the cmd-builder at L384 emits vitest/jest. Document the prefer-vitest fallback.
-** TODO [#B] heavy-box comment inserts non-comment lines :bug:solo:
+** TODO [#B] heavy-box comment inserts non-comment lines :bug:solo:next:
=modules/custom-comments.el:427= — =cj/--comment-heavy-box= interior/empty lines carry no comment prefix, so in line-comment languages (elisp, Python) C-; C h injects syntax-breaking bare =*...= lines. The existing test characterizes the broken output (asserts =^\*.*\*$=). Prefix interiors like =cj/--comment-box= does; add the missing min-length validation (negative width hits make-string with a raw error); fix the test to assert corrected output. From the 2026-06 config audit.
** TODO [#B] jumper: register collisions and dead-marker errors :bug:solo:
@@ -1305,7 +1297,7 @@ Nothing requires =modules/ledger-config.el= (verified by grep), so .dat/.ledger/
:END:
Spec: [[id:4bfc2011-8ffc-4765-8886-91df12141171][messenger-unification-spec.org]] (Draft, 2026-06-11). One library (=cj-messenger-lib.el=) gives every messenger the same shape: chat windows rise from the bottom (the signel rule, generalized), C-c C-c confirms, C-c C-k cancels, C-c C-a attaches — dispatched per backend through a registry + minor mode. Signel already conforms (reference backend); telega and slack join in phases 2-3; ERC later. All eight decisions settled 2026-06-11 (cancel closes an idle window; telega's filter-cancel shadow accepted; slack rooms join the bottom rule). Spec held open — Craig has more ideas to fold in before it's marked Ready.
-** DOING [#B] Migrate All Terminals From Vterm to Ghostel
+** PROJECT [#B] Migrate All Terminals From Vterm to Ghostel
:PROPERTIES:
:LAST_REVIEWED: 2026-06-04
:END:
@@ -1365,7 +1357,7 @@ Folded the external review via spec-response. Craig accepted D1-D5; baked them p
*** 2026-06-04 Thu @ 23:30:18 -0500 External re-review: ready
Re-reviewed [[id:b54c94a0-d762-4b41-afd7-cf5593ce6675][docs/specs/vterm-to-ghostel-migration-spec-implemented.org]] after incorporation. Verdict: =Ready=. No further blocking review notes; implementation can start from the phase plan and acceptance criteria in the spec.
-** DOING [#B] Module-by-module hardening
+** PROJECT [#B] Module-by-module hardening
:PROPERTIES:
:LAST_REVIEWED: 2026-06-05
:END:
@@ -2704,23 +2696,17 @@ configuration (=text-config=, =diff-config=, =ledger-config=,
=games-config=, =mu4e-org-contacts-setup=, =telega-config=,
=httpd-config=, =org-agenda-config-debug=).
-** TODO [#B] org-roam :config triggers the 15-20s refile scan synchronously at first idle :bug:solo:
+** TODO [#B] org-roam :config triggers the 15-20s refile scan synchronously at first idle :bug:solo:next:
=modules/org-roam-config.el:78-79= — org-roam is =:defer 1=, so its :config calls =cj/build-org-refile-targets= at 1s idle, BEFORE the 5s background timer (=org-refile-config.el:144-151=); on a cold cache the 30k-file scan runs inline and freezes Emacs at first idle. Drop the call — org-roam is loaded long before the 5s timer fires. Likely a player in the filed org-capture 15-20s perf task (=[#B] Optimize org-capture target building performance=) — check both together. From the 2026-06 config audit.
-** TODO [#B] rulesets page-me notifications should name the source project :feature:quick:
-:PROPERTIES:
-:LAST_REVIEWED: 2026-06-13
-:END:
-From the roam inbox: the page-me workflow should always identify which project emitted the notification. Add or request a project/source label in the rulesets notification path so a page is actionable when multiple agents/projects are active. Not marked solo here because the implementation likely belongs in the rulesets project rather than this Emacs config.
-
-** TODO [#B] Scratch buffer background a shade lighter than default :feature:
+** TODO [#B] Scratch buffer background a shade lighter than default :feature:next:
Make *scratch* just-noticeably lighter than the normal background so it reads as the scratch buffer. Simplest is a buffer-local face remap on *scratch*; Craig is fine routing it through org-faces if a theme hook is wanted. The exact lightening delta is an aesthetic call to tune visually. From the roam inbox.
-** TODO [#B] Stale elpa gptel shadows the local fork — likely the gptel-magit root :bug:quick:solo:
+** TODO [#B] Stale elpa gptel shadows the local fork — likely the gptel-magit root :bug:quick:solo:next:
=elpa/gptel-0.9.8.5= is still installed alongside the =~/code/gptel= fork (=ai-config.el:383=); package activation puts the elpa dir + autoloads on load-path, so which copy wins depends on ordering, and a mixed load (fork .el + elpa .elc) produces "impossible" bugs. =gptel-magit= (elpa) declares gptel as a dependency, so IT may be pulling the stale copy — check this first when working the open "[#B] Investigate gptel-magit not working properly" task. Fix: =package-delete= the elpa gptel + remove from .localrepo so the fork is the only copy on disk. From the 2026-06 config audit.
2026-06-15: tried deleting =elpa/gptel-0.9.8.5= standalone. The fork loaded correctly and gptel-magit still worked via use-package =:commands= autoloads, BUT package activation then printed "Unable to activate package gptel-magit / Required package gptel-0.9.8 unavailable" on every startup and test run (gptel-magit declares gptel as a package dependency that no longer resolves). Reverted. This can't be done standalone — it must be paired with the gptel-magit dependency fix (drop gptel-magit's package dep, or repackage the fork into .localrepo as gptel). Do it together with the gptel-magit investigation task.
-** TODO [#B] theme-studio: dashboard preview icons missing, list items unthemed :bug:studio:
+** TODO [#B] theme-studio: dashboard preview icons missing, list items unthemed :bug:studio:next:
Found while theme-testing the live dashboard against the preview.
- The navigator icons don't render in the preview at all, showing as mojibake. The nerd-font glyphs have no font fallback in the browser.
- No way to set the color of the project, bookmark, and recent-files list items. The preview renders those entries as plain unstyled text, and the dashboard app exposes no editable face for them.
@@ -2746,18 +2732,8 @@ Design import handling for unstructured color sources such as Emacs themes, CSS
- Add explicit organization tools rather than hidden inference: group selected colors into a column, suggest hue groups as a preview/action, sort imported colors for inspection, and promote a color from an import bucket into a normal column.
- Consider a compact imported/captured bucket UI for large unstructured imports while preserving per-color column ids internally.
-** TODO [#B] theme-studio: org-agenda app + agenda preview :feature:theme-studio: :studio:
+** TODO [#B] theme-studio: org-agenda app + agenda preview :feature:theme-studio: :studio:next:
Break the org-agenda-* plus scheduling / deadline / calendar / clocking / filter faces out of the overloaded org-mode app into a dedicated org-agenda pane (org-mode-line-clock* stay in org-mode), with a representative week-agenda preview at natural item frequency. Keywords, priorities, and tags render live via org-faces / org-mode through the locate registry (hover-only there). Same five-file bespoke-app pattern as org-faces. Depends on the preview-locate feature. Partly subsumes the "break org-mode preview into grouped subsections" task.
-** TODO [#B] theme-studio palette generator :feature:studio:
-:PROPERTIES:
-:LAST_REVIEWED: 2026-06-13
-:END:
-Spec draft: [[id:2df157b8-c7c1-47a9-b080-d9586c6f424c][theme-studio-palette-generator-spec-doing.org]].
-
-Build a constraint-first palette generator for Theme Studio: start from bg/fg, generate editable palette columns in OKLCH, preview candidate columns before applying them, and apply proposals by append/replace/regenerate modes while preserving stable column ids and existing assignments where possible. V1 is palette-only, not automatic face assignment; generator output becomes normal editable columns after apply.
-
-** TODO [#B] theme-studio: preview element locate (hover + click) :feature:theme-studio:spec: :spec:studio:
-General preview interaction: hover any element for its section / face / value, click a current-pane element to flash and jump to its assignment row, off-pane elements hover-only (not clickable). Built on a face -> owning-app registry that previews also read for cross-pane live rendering. Spec: [[id:fbcf0e20-1328-42b4-aa36-3401509e7816][theme-studio-preview-locate-spec.org]]. Prerequisite for the richer org-agenda preview.
** TODO [#B] theme-studio seeding engine :feature:studio:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-13
@@ -2793,7 +2769,7 @@ This may be cancelled if the extra distinction makes the generator harder to und
:END:
Package faces model =inherit= explicitly, but UI faces currently expose only fg/bg/style fields in the table and generated theme output. Before implementing UI-face inheritance, write and review a small spec that defines: which UI faces get an inherit selector, how own defaults from =emacs-default-faces.json= appear versus effective inherited values, how export/import stores cleared vs inherited vs explicit values, how preview resolution follows UI inherit chains, and what browser gates prove the behavior. This touches the UI model, generated defaults, export format, preview rendering, and reset semantics, so it should not be slipped in as a refactor.
-** TODO [#B] transcription: stderr never reaches the log, video transcripts stranded in /tmp :bug:solo:
+** TODO [#B] transcription: stderr never reaches the log, video transcripts stranded in /tmp :bug:solo:next:
From the 2026-06 config audit, =modules/transcription-config.el=:
- =:210= — =make-process :stderr= with a file PATH creates a BUFFER named like the path (verified by probe); the "Errored. Logs in <file>" notification points at a log without the error text, and the hidden stderr buffer leaks per transcription. Route stderr into the process buffer or write it out in the sentinel.
- =:370-374= — video path derives txt/log from the temp mp3's /tmp path; the transcript lands in /tmp and dies on reboot, contradicting the "alongside the source" docstring. Pass the video's path as the output base.
@@ -2813,23 +2789,27 @@ Easy prefix candidates (home-row-leaning, TTY-safe), same leaf keys under each:
While in here, audit individual leaf chords for other non-TTY keys (any =C-RET=, super/hyper bindings — terminals can't send super/hyper either) and note or remap them. Verify the result in an actual =emacs -nw= / =emacsclient -nw= frame, not just GUI. Relates to the standing "org-mode keybinding consolidation" reminder.
-** TODO [#B] Unified popup placement and dismissal rules :feature:
+** TODO [#A] Unified popup placement and dismissal rules :feature:
All transient popups should follow one set of principles. Placement: when the Emacs frame is wider than tall, the popup rises from the right; when square or taller, from the bottom — settle the aspect-ratio threshold and the pop-out percentage. Dismissal: C-c C-c when there's an accept action, C-c C-k when there's a cancel, otherwise =q= closes the window. This generalizes two existing tasks — ai-term adaptive placement (the aspect-ratio docking) and the messenger window/key unification spec (the C-c C-c / C-c C-k dismissal) — into one config-wide policy. From the roam inbox.
-** TODO [#C] theme-studio: drop the too-similar-colors message below the palette :refactor:studio:
+** TODO [#C] theme-studio: alphabetize the assignment view list below the package divider :feature:quick:solo:studio:next:
+Sort the assignment view list alphabetically anywhere below the divider for the package views. From the roam inbox 2026-06-15.
+** TODO [#C] theme-studio: calibre package doesn't color properly :bug:studio:
+The calibre package preview has no elements to theme in the search list, and coloring switches to the string color on mismatched quotes. Investigate, then record a diagnosis and solution in this task before fixing. From the roam inbox 2026-06-15.
+** TODO [#C] music: extract faces for music config :refactor:quick:solo:next:
+Pull the music-config faces out to the theme (the config no longer defines faces directly): playlist name, status (paused, etc.), two mode colors per "button" (on vs off), a per-key symbol+text color, and a color for all other labels. Pairs with the 2026-06-14 face-stripping work (music-config faces were removed there and are currently undefined until the theme defines them). From the roam inbox 2026-06-15.
+** TODO [#C] music: show song information in the modeline :feature:
+Show basic song information in the modeline, with streaming-source support too. Write a spec for this one first. From the roam inbox 2026-06-15.
+** TODO [#C] theme-studio: drop the too-similar-colors message below the palette :refactor:studio:next:
Remove the too-similar-colors warning under the palette display. It isn't useful there; the same information is reachable per-assignment through the inline contrast field. From the roam inbox 2026-06-15.
-** TODO [#C] theme-studio: raise the max color spans to 5 :feature:studio:
+** CANCELLED [#C] theme-studio: raise the max color spans to 5 :feature:studio:
+CLOSED: [2026-06-15 Mon 22:52]
Increase the palette's maximum span count to 5, for a smoother, slower transition across a color. From the roam inbox.
-*** VERIFY which control caps below 5 — current maxes are all 8
+*** CANCELLED which control caps below 5 — current maxes are all 8
+CLOSED: [2026-06-15 Mon 22:52]
On review the per-column span control, the ground span control, and regenColumn all already cap at 8 (well above 5), so there's no sub-5 limit to raise. Either 5 is already reachable, or the intended control is a different one (e.g. the generator emits base-only columns — spanCount is hardcoded 0 in palette-generator-ui.js). Need Craig to point at the control he's hitting.
-** TODO [#C] theme-studio: compact the contrast column to a half-filled symbol :solo:quick:studio:
-Represent contrast as a colored number colored like the current text. The word passed is unnecessary
-** TODO [#C] archsetup Waybar Wi-Fi module should show no-internet state :feature:
-:PROPERTIES:
-:LAST_REVIEWED: 2026-06-13
-:END:
-From the roam inbox: the Waybar Wi-Fi module should distinguish "connected to an access point" from "connected and has internet." Add a no-internet state or indicator to the archsetup Waybar configuration. Not marked quick/solo because it needs the archsetup environment and live network-state verification.
-
+** TODO [#C] theme-studio: compact the contrast column to a number :solo:quick:studio:next:
+Represent contrast as a colored number colored like the current text. The word "passed" is unnecessary
** TODO [#C] Build an Org-native API workspace :feature:test:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-02
@@ -3303,24 +3283,14 @@ Design: [[id:c713b431-ae14-498d-aba9-b84d52f981b6][docs/specs/debug-profiling-sp
Implement via =/start-work= against the design — branch =feat/debug-profiling=, commits decomposed along the test-first split-for-testability boundary. Once shipped, use it as the v1 exercise on the queued [#B] org-capture target-building investigation.
-** TODO [#C] Color-family per-hex hint override :feature:
-:PROPERTIES:
-:LAST_REVIEWED: 2026-06-11
-:END:
-For the ~1 color per palette that sits on a ramp-collision point (e.g. yellow+2 on the distinguished palette, which by every hex signal belongs to the olive ramp though its name says gold), automatic grouping cannot recover the designer's intent. Add a per-hex family override: drag a swatch to a different column, store the override keyed by hex (never the name, so renaming is still free), consult it after the LCCL clustering, and drop/mark-stale it when the hex changes substantially. Export stays mostly flat; only overrides are extra metadata. Both reviews recommend this exact shape; details in =~/color-sorting-fable.org= (§ "The irreducible case") and =~/color-sorting-codex.org= (§ "What to store").
-
** TODO [#C] Consider consolidating/harmonizing the UI in all Message Clients
:PROPERTIES:
:LAST_REVIEWED: 2026-06-06
:END:
They should have the same UI paradigms and patters for consistency.
-** TODO [#C] Dirvish: free D for hard-delete, move duplicate :feature:quick:
+** TODO [#C] Dirvish: free D for hard-delete, move duplicate :feature:quick:next:
In dirvish, keep =d= = delete (=dired-do-delete=), move duplicate (=cj/dirvish-duplicate-file=, currently =D=) to another key, and bind =D= = =sudo rm -rf= for a forced hard delete — capital for the more destructive op. Craig's note says "duplicate on 2"; confirm that's the intended key, and guard the sudo path carefully before wiring. From the roam inbox.
-** TODO [#C] dupre-clear theme — contrast-first AAA sibling :feature:
-Build a new theme (working name "dupre-clear", final name TBD) that takes dupre's color identity and rebuilds it Prot's way: contrast-first, targeting WCAG AAA (~7:1 on the ground), where the in-progress dupre revision is mood/depth-first and lands at AA. Same hues (dupre blue, emerald, gold, terracotta, regal violet, mint) brightened to clear the AAA floor; same modus-style role mapping (blue keywords bold, gold functions, violet types, emerald strings, terracotta constants, silver default, warm-grey comments, metallic greys, navy + regal fills). Build the dupre revision first; this reuses its hue choices as the starting point.
-
-Full design + methodology + starting palette + open questions in the spec: [[id:20df7f50-4759-47ba-9782-8dd25a2e173e][docs/specs/dupre-clear-theme-spec.org]]. Key prerequisite/context: the dupre-redesign entry in =.ai/session-context.org= (the AA palette this brightens). Hardest slot: blue keywords (a deep dupre blue can't be AAA on near-black — decide brighten vs keep-AA-exception vs lift-the-ground).
** TODO [#C] Evaluate jamescherti essential-emacs-packages list :quick:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-11
@@ -3351,19 +3321,6 @@ From the 2026-06-11 brainstorm. Goal: keep [[file:~/sync/org/contacts.org][conta
** TODO [#C] Google Voice in Emacs — SMS + dialer investigation :feature:
From the 2026-06-11 messenger-unification brainstorm. Google Voice has no official API; the viable routes ride the Matrix bridge ecosystem's reverse engineering (mautrix-gvoice). Research pass to establish the 2026 state of play: (1) is mautrix-gvoice healthy and what does its auth flow look like now; (2) any better-maintained alternative (CLI/daemon) for the signel-pattern architecture (external daemon + JSON-RPC + thin Emacs chat client); (3) does call initiation (ring-linked-phone-then-connect, Emacs as dialer) survive in the current protocol — two-way audio in Emacs is out of scope (WebRTC); (4) ToS/account-flag risk assessment for Craig's account. Output: a recommendation doc in docs/design/ naming the architecture (signel-pattern daemon vs Matrix bridge + ement.el) or a no-go with reasons. If go, GV becomes a registered backend under the messenger-unification convention (see the [#B] task below).
-** TODO [#C] gptel-magit activation fails on velox :bug:quick:
-:PROPERTIES:
-:LAST_REVIEWED: 2026-06-01
-:END:
-Surfaced 2026-05-25 while diagnosing an unrelated load failure over SSH. velox-specific — the workstation has a current gptel and does not show it.
-
-At startup (and reproducibly in batch) velox logs: "Unable to activate package `gptel-magit'. Required package `gptel-0.9.8' is unavailable." gptel-magit depends on gptel >= 0.9.8 and velox's installed gptel is older or missing, so it can't activate. A startup warning, not a blocker.
-
-Reproduce:
-: emacs --batch --no-site-file -L . -L modules --eval "(package-initialize)" --eval "(message \"done\")" 2>&1 | grep -i gptel
-
-Next step: check the installed gptel version (=(assq 'gptel package-alist)= or =M-x package-list-packages=), update gptel to >= 0.9.8, then re-evaluate gptel-magit activation. If gptel was pinned/held on velox, reconcile the pin against the gptel-magit dependency.
-
** TODO [#C] GPTel Work :feature:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-01
@@ -3862,6 +3819,19 @@ Surface current-buffer or project-wide errors and warnings. Useful
both as a "what's broken right now" check and as input to the
patch-narrative buffer / commit-intent workbench above.
+*** TODO [#D] gptel-magit activation fails on velox :bug:quick:
+:PROPERTIES:
+:LAST_REVIEWED: 2026-06-01
+:END:
+Surfaced 2026-05-25 while diagnosing an unrelated load failure over SSH. velox-specific — the workstation has a current gptel and does not show it.
+
+At startup (and reproducibly in batch) velox logs: "Unable to activate package `gptel-magit'. Required package `gptel-0.9.8' is unavailable." gptel-magit depends on gptel >= 0.9.8 and velox's installed gptel is older or missing, so it can't activate. A startup warning, not a blocker.
+
+Reproduce:
+: emacs --batch --no-site-file -L . -L modules --eval "(package-initialize)" --eval "(message \"done\")" 2>&1 | grep -i gptel
+
+Next step: check the installed gptel version (=(assq 'gptel package-alist)= or =M-x package-list-packages=), update gptel to >= 0.9.8, then re-evaluate gptel-magit activation. If gptel was pinned/held on velox, reconcile the pin against the gptel-magit dependency.
+
** TODO [#C] Implement EMMS-free music-config architecture :refactor:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-01
@@ -4057,7 +4027,7 @@ used to handle. Per-module fixups for ledger, AUCTeX, eshell, mu4e
compose, and the three =prog-*= modules. See the design doc for the
full translation table, migration steps, tests, and risks.
-** TODO [#C] music-config option-combination audit + tests :test:
+** TODO [#C] music-config option-combination audit + tests :test:next:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-06
:END:
@@ -4119,7 +4089,7 @@ The core functionality is implemented but needs debugging before it's production
3. Refine toggle behavior based on testing
4. Document the final keybindings and workflow
-** TODO [#C] Page-down in a long completing-read selects and dismisses the list :bug:
+** TODO [#C] Page-down in a long completing-read selects and dismisses the list :bug:next:
In a very long completing-read (vertico), Page-Down selects an item and the list vanishes instead of paging, forcing a cancel. Investigate the completion stack's next-page handling; likely needs vertico-scroll-up / vertico-scroll-down bound in vertico-map. From the roam inbox.
** VERIFY [#C] page-signal pager account deregistered — re-registration needs your hands
:PROPERTIES:
@@ -4155,10 +4125,10 @@ Evaluate against these projects' languages: elisp (edebug already works), Python
Do this after the F-key rework ticket ships so F5 is the only hole left.
-** TODO [#C] Pull a fullscreen terminal window away with C-; b + arrow :feature:
+** TODO [#C] Pull a fullscreen terminal window away with C-; b + arrow :feature:next:
When a terminal fills the frame, =C-; b= then a right or down arrow should shrink the window from that edge, reducing its width or height so another buffer can share the screen without leaving the terminal. Relates to the ai-term adaptive placement and unified-popup tasks. From the roam inbox.
-** TODO [#C] Remove unused system-power keybindings :refactor:quick:
+** TODO [#C] Remove unused system-power keybindings :refactor:quick:next:
=modules/system-commands.el= binds shutdown (=C-; ! s=), reboot (=C-; ! r=), restart-Emacs (=C-; ! e=) and friends under the =C-; != prefix. Craig rarely uses them and wants the key real-estate back. Drop the bindings he doesn't use; the completing-read menu can still reach the rare ones. Confirm the exact set to keep before unbinding. From the roam inbox.
** TODO [#C] Review and rebind M-S- keybindings :refactor:
@@ -4234,7 +4204,7 @@ Rather than cramming all org-mode preview into one pane, split into groups so ea
build-theme.el's UI tier passes inherit=nil to --attrs, so a UI face that relies only on its inherit field (no explicit fg/bg) loses the inheritance in the generated theme, while the studio preview shows the inherited color via resolveUiAttr. The package tier already emits :inherit; the UI tier should match. Surfaced while diagnosing why mode-line-inactive looked off in Emacs versus the preview (that case had explicit colors and turned out to be a stale deploy, but the inherit gap is real for any inherit-only UI face).
** TODO [#C] theme-studio: elfeed ignores theme assignments :studio:studio:
The preview shows theme colors, but elfeed itself renders all-white with no variation. Note: this may be the shr-rendered entry/article view (elfeed-show), where color often comes from the document rather than the theme — confirm whether the symptom is in the search list or the article view. From the roam inbox.
-** TODO [#C] theme-studio face-consistency check :feature:studio:
+** TODO [#C] theme-studio face-consistency check :feature:studio:next:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-10
:END:
@@ -4252,7 +4222,8 @@ Bake into the tool (a lint surfaced in the UI) or run as a build-time check (see
:END:
Craig, 2026-06-11 manual-test walk: the color picker's background is hard to distinguish from the page background. Give the picker panel a visibly distinct background or a highlighted border so it stands out. Pin with a gate asserting the picker element carries the distinct style.
-** TODO [#C] theme-studio reconsider the JSON show button :feature:quick:studio:
+** CANCELLED [#C] theme-studio reconsider the JSON show button :feature:quick:studio:
+CLOSED: [2026-06-15 Mon 22:56]
:PROPERTIES:
:LAST_REVIEWED: 2026-06-13
:END: