summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-02-14 13:14:40 -0600
committerCraig Jennings <c@cjennings.net>2026-02-14 13:14:40 -0600
commit82f10cc8258f17fbc42ed54b586385bfdf3f2091 (patch)
tree4e10ac10a4a664843b90cbc4220749c06a39c881
parent176ea668cdd83beddd54a24334a8a9db3cc87dfb (diff)
refactor(tasks): migrate todo.org to Open Work / Resolved formatHEADmain
Decouple task tracking from V2MOM strategic framework. Archive full V2MOM history to v2mom.org, replace todo.org with flat task list under Emacs Open Work / Emacs Resolved headings. Merge duplicate tasks (org-noter, buttercup, localrepo, lorem-optimum). 29 open tasks, no method grouping.
-rw-r--r--todo.org1519
-rw-r--r--v2mom.org1671
2 files changed, 1780 insertions, 1410 deletions
diff --git a/todo.org b/todo.org
index 27b5e366..3258f6c1 100644
--- a/todo.org
+++ b/todo.org
@@ -1,35 +1,57 @@
-#+TITLE: Emacs Config V2MOM and Tasks
+#+TITLE: Emacs Config Tasks
#+AUTHOR: Craig Jennings
-#+DATE: 2025-10-31
-#+FILETAGS: :v2mom:active:
-* Instructions
+* Emacs Open Work
-This inbox contains ONLY tasks that serve the V2MOM vision. Before adding any task here, ask:
-1. Does it serve the Vision?
-2. Does it align with the Values?
-3. Is it addressed in the Methods?
-4. Does it overcome an Obstacle?
-5. Does it improve a Metric?
+** VERIFY [#B] Continue org-noter custom workflow implementation (IN PROGRESS)
-If the answer is "no" to all five → DON'T ADD IT.
+Continue debugging and testing the custom org-noter workflow from 2025-11-21 session.
+This is partially implemented but has known issues that need fixing before it's usable.
-V2MOM is located at: [[file:docs/emacs-config-v2mom.org][emacs-config-v2mom.org]]
-Research/ideas that don't serve vision: [[file:docs/someday-maybe.org][someday-maybe.org]]
+**Last worked on:** 2025-11-21
+**Current status:** Implementation complete but has bugs, needs testing
-* Method 1: Make Using Emacs Frictionless [16/24]
-** VERIFY [#B] Fix org-noter (reading/annotation workflow currently "so painful")
+**Known Issues to Fix:**
-High priority - daily pain point.
+1. **Double notes buffer appearing when pressing 'i' to insert note**
+ - When user presses 'i' in document to insert a note, two notes buffers appear
+ - Expected: single notes buffer appears
+ - Need to debug why the insert-note function is creating duplicate buffers
-** VERIFY [#B] Fix mail attachment workflow (currently awkward)
+2. **Toggle behavior refinement needed**
+ - The toggle between document and notes needs refinement
+ - May have edge cases with window management
+ - Need to test various scenarios
-Daily workflow improvement.
+**Testing Needed:**
-** DONE [#B] Optimize org-agenda performance using built-in profiler
+1. **EPUB files** - Test with EPUB documents (primary use case)
+2. **Reopening existing notes** - Verify it works when notes file already exists
+3. **Starting from notes file** - Test opening document from an existing notes file
+4. **PDF files** - Verify compatibility with PDF workflow
+5. **Edge cases:**
+ - Multiple windows open
+ - Splitting behavior
+ - Window focus after operations
-THE BOTTLENECK. Currently 30+ seconds, target < 5 seconds.
-Use M-x profiler-start before Method 3 debug-profiling.el is built.
+**Implementation Files:**
+- modules/org-noter-config.el - Custom workflow implementation
+- Contains custom functions for document/notes toggling and insertion
+
+**Context:**
+This custom workflow is designed to make org-noter more ergonomic for Craig's reading/annotation
+workflow. It simplifies the toggle between document and notes, and streamlines note insertion.
+The core functionality is implemented but needs debugging before it's production-ready.
+
+**Next Steps:**
+1. Debug the double buffer issue when pressing 'i'
+2. Test all scenarios listed above
+3. Refine toggle behavior based on testing
+4. Document the final keybindings and workflow
+
+** VERIFY [#B] Fix mail attachment workflow (currently awkward)
+
+Daily workflow improvement.
** TODO [#B] Optimize org-capture target building performance
@@ -46,830 +68,67 @@ Changes in progress (modules/auth-config.el):
- Use external pinentry (pinentry-dmenu) in GUI
- Requires env-terminal-p from host-environment module
-** DONE [#C] Verify format-buffer hands off to shfmt in shell scripts
-
-Need to verify that the format-buffer command correctly delegates to shfmt when
-formatting shell scripts. May not be configured or may use wrong formatter.
-
-**Problem:**
-- Unknown if format-buffer works in shell-script-mode
-- May not be using shfmt (should use shfmt for shell scripts)
-- May be using a different formatter (or no formatter)
-- Need to verify configuration and test manually
-
-**Investigation:**
-1. Find format-buffer implementation:
- - Search for defun format-buffer in modules/
- - Check if it's in prog-general.el or separate module
- - Review how it selects formatters per mode
-2. Check shfmt configuration:
- - Is shfmt installed? `which shfmt`
- - Is shfmt configured for shell-script-mode?
- - What are the shfmt command-line arguments?
-3. Test manually:
- - Create test shell script with bad formatting
- - Run format-buffer command
- - Verify it uses shfmt (not something else)
- - Check formatted output is correct
-
-**Expected Behavior:**
-1. In shell-script-mode buffer
-2. Run format-buffer (or whatever the command is)
-3. Should invoke shfmt to format the buffer
-4. Output should be properly formatted shell code
-5. Should preserve shebang and script functionality
-
-**Possible Issues:**
-
-A. **shfmt not installed**
- - Check: `pacman -Q shfmt` or `which shfmt`
- - Install if missing: `sudo pacman -S shfmt`
-
-B. **format-buffer not configured for shell**
- - May only work for elisp/python/etc.
- - Need to add shell-script-mode configuration
- - Need to specify shfmt command
-
-C. **Wrong formatter used**
- - May be using bashfmt, beautysh, or other tool
- - Should specifically use shfmt (preferred)
-
-D. **format-buffer doesn't exist**
- - May be using different command name
- - Check for format-all, apheleia, or custom function
-
-**Manual Test:**
-Create test file:
-```bash
-#!/bin/bash
-# Poorly formatted script
-if [ -f "test.txt" ];then
-echo "found"
-else
- echo "not found"
-fi
-for i in 1 2 3;do echo $i;done
-```
-
-Expected after shfmt:
-```bash
-#!/bin/bash
-# Poorly formatted script
-if [ -f "test.txt" ]; then
- echo "found"
-else
- echo "not found"
-fi
-for i in 1 2 3; do
- echo $i
-done
-```
-
-**Related Commands to Check:**
-- format-buffer
-- format-all-buffer
-- apheleia-format-buffer
-- Custom cj/format-buffer
-
-**Related Files:**
-- modules/prog-general.el (likely location of format-buffer)
-- modules/prog-shell.el (shell-specific config)
-- Check for apheleia or format-all package config
-
-**Related Docs:**
-- shfmt documentation: https://github.com/mvdan/sh
-- format-all or apheleia package docs (whichever is used)
-- V2MOM Method 1: Frictionless (formatting should just work)
-
-**Success Criteria:**
-- format-buffer (or equivalent) command exists
-- Works in shell-script-mode buffers
-- Uses shfmt as the formatter
-- Produces correctly formatted shell code
-- Doesn't break script functionality
-- Documented what command to use and how it works
-
-**If It Doesn't Work:**
-1. Install shfmt: `sudo pacman -S shfmt`
-2. Configure formatter (apheleia or format-all):
- ```elisp
- ;; Example configuration
- (add-to-list 'apheleia-formatters
- '(shfmt . ("shfmt" "-i" "2" "-ci")))
- (add-to-list 'apheleia-mode-alist
- '(shell-script-mode . shfmt))
- ```
-3. Test again
-4. Document in prog-shell.el
-
-**Note:**
-Priority [#C] because formatting is nice-to-have. Can format manually with shfmt
-if needed. Low priority but good for maintaining code quality in shell scripts.
-
-Normal case: File with #!/bin/bash at start should get +x permission."
- (let ((test-file (make-temp-file "test-script-" nil ".sh")))
- (unwind-protect
- (progn
- ;; Write shebang to file
- (with-temp-file test-file
- (insert "#!/bin/bash\necho hello\n"))
- ;; Remove execute permission
- (set-file-modes test-file #o644)
- (should-not (file-executable-p test-file))
- ;; Open file and trigger function
- (with-current-buffer (find-file-noselect test-file)
- (cj/make-script-executable)
- (kill-buffer))
- ;; Verify file is now executable
- (should (file-executable-p test-file)))
- (delete-file test-file))))
-```
-
-**Related Files:**
-- modules/prog-shell.el:158-167 (function to test)
-- tests/test-prog-shell-make-script-executable.el (NEW - create this)
-- ai-prompts/quality-engineer.org (testing guidance)
-
-**Related Docs:**
-- quality-engineer.org: File system testing best practices
-- Recent test examples: test-custom-buffer-file-*.el (file operations)
-- Emacs manual: File permissions and file-modes function
-
-**Success Criteria:**
-- Comprehensive test file covering all normal/boundary/error cases
-- All tests pass on Linux
-- Tests properly clean up temp files
-- Tests verify actual file permission changes
-- Tests verify message output
-- No false positives (making non-script files executable)
-- No false negatives (missing files that should be executable)
-- Tests document expected behavior (serve as specification)
-
-**Estimated Tests:**
-- 6-8 normal cases (different shebangs)
-- 8-10 boundary cases (edge conditions)
-- 5-6 error cases (failure handling)
-- Total: ~20-25 tests
-
-**Note:**
-Priority [#B] because this function runs on every save in shell-script-mode and
-modifying file permissions incorrectly could cause security issues or workflow
-problems. Needs testing before any refactoring or changes.
-
** VERIFY [#C] Fix EMMS keybinding inconsistency with other buffers
EMMS keybindings conflict with standard buffer keybindings, causing mistypes.
Results in accidental destructive actions (clearing buffers), requires undo + context switch.
Violates Intuitive value - muscle memory should help, not hurt.
-** DONE [#D] Frequently used org-mode keybindings under C-; o
-
-Add quick access keybindings for common org commands (org-table, org-reveal, etc.) under C-; o.
-Makes org-mode operations more frictionless.
-Moved from inbox 2025-11-07.
-
-** DONE [#A] Music player is broken - mpd/mopidy need replacement
-CLOSED: [2025-11-16 Sun 18:35] SCHEDULED: <2025-11-15 Fri>
-
-music-config.el integration with mpd and mopidy is broken. Need to migrate to
-a different music player solution. Investigate alternatives:
-- emms with VLC/mpv backend
-- bongo player
-- Simple mpv integration
-- Other lightweight music player packages
-
-** DONE [#A] Fix recording workflow - phone call audio not captured (44 dB volume loss)
-CLOSED: [2025-11-14 Thu]
-
-✅ **Fixed by replacing amerge+pan with amix FFmpeg filter**
-
-**Problem:**
-On recorded calls, only one side was captured (user's microphone), not the other person's voice.
-Phone call audio was too quiet to transcribe (44 dB volume loss).
-
-**Root Cause:**
-FFmpeg's `amerge+pan` filter combination caused massive volume loss when mixing microphone
-and system monitor inputs. The `pan` filter reduced volume by 50% and `amerge` had issues
-with PulseAudio/PipeWire compatibility.
-
-**Solution:**
-Replaced `amerge=inputs=2[merged];[merged]pan=mono|c0=0.5*c0+0.5*c1` with `amix=inputs=2:duration=longest`
-filter. The `amix` filter properly mixes inputs without volume loss.
-
-**Changes Made:**
-- Changed FFmpeg filter from `amerge+pan` to `amix` (modules/video-audio-recording.el:513)
-- Increased default system volume from 0.5 to 2.0 (modules/video-audio-recording.el:76)
-- Added diagnostic tool `C-; r w` to show active audio playback
-- Created integration test with real voice recording
-- Fixed batch mode compatibility for tests
-
-**Results:**
-- Volume improved from -66.2 dB to -21.5 dB (44 dB improvement)
-- Test transcription: 100% accurate ("Can you hear me? Testing, one, two, three.")
-- Phone calls now capture both sides correctly
-
-**Testing:**
-Automated integration test verifies monitor capture works with perfect transcription.
-** DONE [#A] Fix Google Calendar password prompts every 15 minutes
-CLOSED: [2025-11-11 Mon]
-
-✅ **Fixed oauth2-auto caching bug**
-
-**Root Cause:**
-oauth2-auto.el version 20250624.1919 had a bug on line 206 that completely
-disabled its internal token cache with `or nil`. This forced every org-gcal
-sync to decrypt oauth2-auto.plist from disk, triggering GPG passphrase prompts
-every ~15 minutes.
-
-**The Bug:**
-```elisp
-;; Line 201-213 in oauth2-auto.el (BEFORE fix)
-(defun oauth2-auto--plstore-read (username provider)
- "Read the data for USERNAME and PROVIDER from the cache, else from plstore."
- (let ((id (oauth2-auto--compute-id username provider)))
- ; Assume cache is invalidated. FIXME
- (or nil ;(gethash id oauth2-auto--plstore-cache) ;; BUG: cache disabled!
- (let ((plstore (plstore-open oauth2-auto-plstore)))
- ...))))
-```
-
-**The Fix:**
-Enabled the internal hash-table cache by removing `or nil`:
-```elisp
-;; Line 201-213 in oauth2-auto.el (AFTER fix)
-(defun oauth2-auto--plstore-read (username provider)
- "Read the data for USERNAME and PROVIDER from the cache, else from plstore."
- (let ((id (oauth2-auto--compute-id username provider)))
- ;; FIXED: Enable cache to prevent repeated GPG passphrase prompts
- (or (gethash id oauth2-auto--plstore-cache) ;; Cache now works!
- (let ((plstore (plstore-open oauth2-auto-plstore)))
- ...))))
-```
-
-**What Changed:**
-1. Modified elpa/oauth2-auto-20250624.1919/oauth2-auto.el:201-213
-2. Removed `or nil` that disabled cache
-3. Added `cj/clear-oauth2-auto-cache` helper function in auth-config.el
-4. Documented fix in auth-config.el commentary (lines 16-22)
-
-**Result:**
-- GPG passphrase prompted ONCE per Emacs session (when first accessing tokens)
-- oauth2-auto now caches tokens in memory (oauth2-auto--plstore-cache)
-- No more interruptions during org-gcal auto-sync every 30 minutes
-- Workflow is now frictionless as intended
-
-**Testing:**
-After restart:
-1. First org-gcal sync prompts for passphrase (expected)
-2. Subsequent syncs use cached tokens (no prompts)
-3. Cache persists until Emacs closes
-
-**Files Modified:**
-- elpa/oauth2-auto-20250624.1919/oauth2-auto.el (cache fix)
-- modules/auth-config.el (documentation + helper function)
-
-Priority [#A] because password prompts every 15 minutes violated "Frictionless" value.
-Fixed 2025-11-11.
-
-** DONE [#A] Fix audio recording device selection - still broken with Jabra headset
-CLOSED: [2025-11-11 Mon]
-
-✅ **Fixed audio recording bug + improved UX**
-
-**Root Cause:**
-Auto-detection only looked for `analog.*stereo` which matched laptop audio but never
-Bluetooth/Jabra devices. User was always recording from laptop mic (silent when using Jabra).
-
-**What Was Fixed:**
-
-1. **Removed broken auto-detection** (lines 58-77)
- - Old code only detected built-in laptop audio
- - Never detected Bluetooth/USB/Jabra devices
- - This is why recordings were silent
-
-2. **Force explicit device selection on first use**
- - C-; r a now prompts for device setup if not configured
- - Suggests quick setup (C-; r c) by default
- - Device selection persists across Emacs sessions
-
-3. **Simplified keybindings to toggle start/stop**
- - C-; r a → Toggle audio recording (start/stop)
- - C-; r v → Toggle video recording (start/stop)
- - Removed separate stop keybindings (A, V)
- - One key to remember, press again to stop!
-
-4. **Added device testing functions** (lines 233-314)
- - C-; r t b → Test both mic + monitor (guided, RECOMMENDED)
- - C-; r t m → Test microphone only (5 sec)
- - C-; r t s → Test system audio/monitor only (5 sec)
- - Catch hardware issues before important recordings
-
-5. **Added modeline recording indicator**
- - 🔴Audio appears when recording audio
- - 🔴Video appears when recording video
- - 🔴A+V appears when recording both
- - Indicator and toggle always in sync (same process variables)
- - Process sentinel auto-clears on crash/kill
-
-**New Workflow:**
-```
-Press C-; r a
- ↓
-First time? → Device setup → Choose Jabra → Start (🔴Audio appears)
- ↓
-Already configured? → Start immediately (🔴Audio appears)
- ↓
-Press C-; r a again → Stop (🔴 disappears)
-```
-
-**Files Modified:**
-- modules/video-audio-recording.el (removed auto-detect, added tests, toggle functions, modeline indicator)
-- modules/modeline-config.el (added 🔴 recording indicator to right side)
-
-**Testing:**
-After Emacs restart:
-1. Press C-; r a
-2. Choose "Bluetooth Headset" (Jabra)
-3. See 🔴Audio in modeline
-4. Speak and play audio
-5. Press C-; r a to stop
-6. Verify recording has audio
-
-Priority [#A] because blocked daily recording and transcription workflows.
-Fixed 2025-11-11.
-
-** DONE [#A] Remove network check from startup (saves 1+ seconds)
-CLOSED: [2025-10-31 Fri]
-
-✅ Deleted blocking ping check. Startup improved from 6.2s to 5.4s.
-Now uses package priorities: .localrepo (200) > online repos (25).
-
-** DONE [#A] Fix cj/goto-git-gutter-diff-hunks (missing function causing errors)
-CLOSED: [2025-11-03 Sun]
-
-✅ Implemented missing function in modules/vc-config.el
-- Added `cj/goto-git-gutter-diff-hunks` function (lines 118-124)
-- Uses consult-line to search for diff markers (^[+\-])
-- Enables interactive jumping to any changed line via C-; v d
-- Function properly documented with docstring
-- No linting issues, compiles cleanly
-
-Quick win completed - 5 minutes actual time.
-
-** DONE [#A] Fix chime-check throw with no catch block
-CLOSED: [2025-11-01 Fri]
-
-Error: "(no-catch --cl-block-chime-check-- nil)"
-Chime was throwing to a catch block that doesn't exist.
-Location: chime package - chime-check() function at line 1540
-Fix: Changed defun to cl-defun to provide implicit catch block for cl-return-from.
-
-Fixed in ~/code/chime.el/chime.el:1540
-
-Added regression test: test-integration-startup-early-return-on-validation-failure
-Created Makefile with test targets (unit, integration, all, by-file, by-name)
-Updated README.org with Development/Testing section
-
-All integration tests pass (5/5) ✅
-
-** DONE [#A] Implement cj/diff-buffer-with-file (compare buffer with saved version)
-CLOSED: [2025-10-31 Fri]
-
-Bound to C-; b D. Weekly need satisfied.
-
-** DONE [#A] Add comprehensive test coverage for video-audio-recording module
-CLOSED: [2025-11-03 Sun]
-
-✅ Created comprehensive test suite following quality-engineer.org standards:
-- 9 test files (8 unit + 1 integration)
-- 83 test cases with 100% pass rate
-- Test categories: Normal, Boundary, Error cases
-- 6 test fixtures for reproducible testing
-- Mocking strategy using cl-letf
-- Integration test validates complete parse→group→friendly-names workflow
-- Tests document bugs in legacy detect functions
-- Critical validation: Bluetooth MAC normalization across component boundaries
-
-✅ Refactored code for testability:
-- Extracted `cj/recording--parse-pactl-output` internal parser
-- Separated I/O from business logic
-
-✅ Fixed all linting warnings (checkdoc):
-- 6 spacing/grammar issues resolved
-- `make lint` now passes cleanly
-
-✅ All changes committed and pushed to all remotes (origin + github)
-
-Commits:
-- 0a69c58: test: Add comprehensive test suite for video-audio-recording module
-- b086539: style: Fix checkdoc warnings in video-audio-recording.el
-
-*** DONE [#C] Add device testing command cj/recording-test-devices
-CLOSED: [2026-02-06 Thu]
-Records 3 seconds of audio.
-Plays it back.
-Confirms devices work before real recording.
-
-*** CANCELLED [#C] Add recording status display (optional via flag, default off)
-CLOSED: [2026-02-14 Sat]
-Emoji modeline icon is sufficient.
-
-*** CANCELLED [#C] Add recording presets
-CLOSED: [2026-02-14 Sat]
-Only used for meetings; emoji icon is good-enough reminder. Gold-plating.
-
-*** CANCELLED [#C] Build recording history buffer
-CLOSED: [2026-02-14 Sat]
-Opening recordings in dirvish is sufficient.
+** TODO [#C] Add post-processing hooks (recording)
-*** TODO [#C] Add post-processing hooks
Auto-compress after recording.
Move to cloud sync directory.
Generate transcript (once transcription workflow exists).
-** DONE [#A] Delay in modeline lines and columns update
-CLOSED: [2025-11-08 Fri]
-
-✅ Fixed modeline position lag by replacing expensive function calls with cached values.
-
-**Problem:**
-- Line/column numbers lagged behind cursor movement
-- Used `line-number-at-pos` which counts from buffer start on every update
-- Performance degraded in large files
-
-**Solution:**
-- Replaced with built-in format specifiers `%l` and `%c` (modeline-config.el:81)
-- These use cached values maintained by line-number-mode and column-number-mode
-- Explicitly enabled line-number-mode in ui-config.el:53
-- Zero performance overhead - cached values update instantly
-
-**Result:**
-- Modeline position now updates instantly with cursor movement
-- No lag, even in large files
-- Maintains same "L:line C:col" format
-
-** DONE [#B] Toggle org-appear on/off
-CLOSED: [2025-11-16 Sat]
-
-✅ **Implemented toggle function with C-c C-a keybinding**
-
-Created `cj/org-appear-toggle` function that toggles org-appear-mode on/off in
-current org buffer. Default is OFF (cleaner for reading), can be toggled ON when
-editing links, then toggled OFF again.
-
-**Implementation:**
-- Removed :disabled flag and :hook (default: OFF)
-- Created cj/org-appear-toggle function with clear user feedback
-- Bound to C-c C-a in org-mode-map (unbound, no conflicts)
-- Tested: toggles correctly, all tests pass
-
-**Usage:**
-- C-c C-a: Toggle on/off
-- Default: OFF (links and emphasis markers stay hidden)
-- Messages show current state clearly
-
-Moved from inbox 2025-11-07. Completed 2025-11-16.
-
-** DONE [#B] Consider implementing cron download of Google Calendar to replace org-gcal
-CLOSED: [2025-11-16 Sat]
-
-Replaced problematic org-gcal OAuth workflow with calendar-sync.el module.
-Implemented pure Elisp .ics parser with timer-based sync (no cron needed).
-
-**Current Problem:**
-From TODO at line 22-66:
-- org-gcal prompts for password every ~15 minutes
-- OAuth token refresh bypasses cache
-- plstore symmetric encryption cache issues
-- Interrupts workflow constantly
-- Makes calendar sync painful instead of seamless
-
-**Proposed Solution:**
-Instead of OAuth-based sync (org-gcal), use Google Calendar's public iCalendar URLs:
-1. Download .ics file via cron (every 15-30 minutes)
-2. Parse .ics file into org-mode format
-3. Update org-agenda files automatically
-4. No OAuth, no passwords, no interruptions
-
-**Benefits:**
-- ✓ No password prompts (public calendar URL or one-time API key)
-- ✓ No OAuth token refresh issues
-- ✓ Runs in background (cron), never interrupts work
-- ✓ Simpler architecture (download → parse → update)
-- ✓ Can work offline (reads last downloaded .ics)
-- ✓ More reliable (fewer moving parts)
-- ✓ No plstore symmetric encryption issues
-
-**Drawbacks:**
-- ✗ Read-only (can't create/update events from Emacs)
-- ✗ Need to manually get calendar iCal URL
-- ✗ Requires cron setup (one-time configuration)
-- ✗ May have sync delay (up to cron interval)
-
-**Investigation:**
-
-1. **Get Google Calendar iCal URL:**
- - Open Google Calendar settings
- - Find "Integrate calendar" section
- - Copy secret iCal address (https://calendar.google.com/calendar/ical/...)
- - Store in auth-source (encrypted)
-
-2. **Test iCal download:**
- ```bash
- curl -o calendar.ics "https://calendar.google.com/calendar/ical/.../basic.ics"
- ```
- - Verify it downloads
- - Check .ics format
- - Confirm events are present
-
-3. **Research iCal parsing:**
- - Does Emacs have built-in iCal parser? (icalendar.el)
- - Check icalendar-import-file function
- - Test parsing downloaded .ics file
- - Verify it creates org entries
-
-4. **Design cron workflow:**
- ```bash
- # Every 15 minutes
- */15 * * * * curl -s "$(cat ~/.calendar-url)" -o ~/calendars/gcal.ics
- ```
- - Downloads silently in background
- - Emacs watches file for changes (file-notify)
- - Auto-reimport when changed
-
-**Possible Implementations:**
-
-A. **Full replacement (recommended):**
- - Remove org-gcal entirely
- - Use cron + icalendar.el
- - Read-only calendar view in org-agenda
- - Create events directly in Google Calendar web UI
-
-B. **Hybrid approach:**
- - Keep org-gcal for writing events
- - Use cron download for reading events
- - Disable org-gcal auto-sync (no password prompts)
- - Manually trigger org-gcal only when creating events
-
-C. **Enhanced cron:**
- - Cron downloads .ics
- - Emacs function parses and updates org files
- - Add file-notify watcher for auto-update
- - Optional: Convert two-way with CalDAV later
-
-**Implementation Sketch:**
-```elisp
-(defun cj/calendar-import-gcal ()
- "Import Google Calendar from downloaded .ics file."
- (interactive)
- (let ((ics-file "~/calendars/gcal.ics")
- (org-file "~/org/calendar.org"))
- (when (file-exists-p ics-file)
- (icalendar-import-file ics-file org-file)
- (message "Imported calendar from %s" ics-file))))
-
-;; Auto-import when .ics file changes
-(file-notify-add-watch
- "~/calendars/gcal.ics"
- '(change)
- (lambda (event) (cj/calendar-import-gcal)))
-```
-
-**Related Files:**
-- modules/org-gcal-config.el (current problematic implementation)
-- Emacs built-in: icalendar.el (iCal parsing)
-- System: crontab -e (download schedule)
-- ~/.authinfo.gpg (store calendar URL securely)
-
-**Related Docs:**
-- Current problem: TODO line 22-66 (password prompts every 15 min)
-- icalendar.el manual: C-h f icalendar-import-file
-- Google Calendar iCal format documentation
-- V2MOM Method 1: Frictionless (no interruptions!)
-
-**Success Criteria:**
-- Calendar events appear in org-agenda
-- No password prompts during work
-- Updates automatically in background (cron)
-- Can work offline with last sync
-- Setup is one-time configuration
-- Simpler than current org-gcal setup
-
-**Testing Plan:**
-1. Get iCal URL from Google Calendar
-2. Test download: `curl URL -o test.ics`
-3. Test import: `M-x icalendar-import-file`
-4. Verify org entries created correctly
-5. Set up cron job
-6. Wait for auto-update
-7. Confirm events in org-agenda
-8. Disable org-gcal auto-sync
-9. Monitor for 1 week (no password prompts?)
-
-**Decision Point:**
-This is a significant architectural change. Need to:
-1. Test proof-of-concept first (manual download + import)
-2. Evaluate if read-only is acceptable
-3. Compare to fixing OAuth password prompts
-4. Consider hybrid approach if two-way sync needed
-
-**Note:**
-Priority [#B] because this could eliminate the #1 daily irritant (password prompts
-every 15 minutes). If proof-of-concept works, this is higher value than fixing
-OAuth issues. Simpler architecture = fewer problems.
-
-** DONE [#B] Add time-zones package for quick timezone lookups
-CLOSED: [2025-11-14 Fri 02:42]
-
-IRRITANT: Need to frequently check time differences between cities (London, Lisbon,
-New Orleans, San Francisco) for meetings and coordination. Currently requires stopping
-work, searching web/using external app, context switching back.
-
-**Pain Point:**
-Multiple times per week, need to know "what time is it in London right now?" or
-"if I schedule this for 2pm my time, what time is that in Lisbon?" This breaks
-flow and requires leaving Emacs.
-
-**Solution:**
-Use time-zones package: https://github.com/xenodium/time-zones
-
-Built-in world-clock exists (M-x world-clock) but lacks two critical features:
-1. Can't interactively add cities with fuzzy search
-2. Can't shift time forward/backward to check future times
-
-time-zones package adds both features - making timezone checks instant and frictionless.
-
-**Expected Workflow:**
-- M-x time-zones (or keybinding C-; T z or similar)
-- Interactively add/remove cities with completion
-- Shift time forward/backward to check meeting times
-- Stay in Emacs, maintain flow
-
-**Files:**
-- Create new module: modules/time-zones-config.el
-- Add require to init.el in appropriate section
-- Configure default cities list (London, Lisbon, New Orleans, San Francisco)
-- Add keybinding (suggest C-; T z for time zones)
-
-**V2MOM Alignment:**
-Method 1 - Frictionless: Eliminates context switch for common timezone queries.
-Intuitive value: Quick keybinding for frequent operation.
-
-** DONE [#B] Fix go-ts-mode-map keybinding error (void-variable)
-CLOSED: [2025-11-03 Sun]
-
-Error: "Debugger entered--Lisp error: (void-variable go-ts-mode-map)"
-Location: modules/prog-go.el - trying to bind keys before mode loads.
-
-✅ Already fixed in commit 196b289 (Nov 2, 2025)
-- Moved keybinding from `:bind (:map go-ts-mode-map ...)` to hook function
-- Keybinding now set in `cj/go-mode-keybindings` called via `:hook`
-- Function executes after mode loads, ensuring keymap exists
-- Today's cleanup: Removed unused forward declarations (lines 34-35)
-
-Fix was: Wrap keybinding in hook function instead of :bind clause.
-Result: No more void-variable error, keybinding works correctly.
-
-** DONE [#B] Fix video/audio recording module (use constantly, just broke)
-CLOSED: [2025-11-03 Sun]
-
-Main issue: No way to select audio devices when multiple are available.
-Plugging in external audio interface broke recording - only captured input, not output.
-
-✅ COMPLETED - Module now has robust device detection and selection.
-
-*** DONE [#A] Add diagnostic command cj/recording-list-devices
-CLOSED: [2025-11-03 Sun]
-
-✅ Created `cj/recording-list-devices` command (C-; r d)
-Shows ALL available PulseAudio/PipeWire sources with drivers and states.
-Displays current configuration.
-Helps debug why auto-detection fails.
-
-*** DONE [#A] Add device selection UI
-CLOSED: [2025-11-03 Sun]
-
-✅ Created TWO selection workflows:
-1. `cj/recording-select-devices` (C-; r s) - Full manual control
- - Select mic and system audio separately
- - Interactive completion with device states
-2. `cj/recording-quick-setup-for-calls` (C-; r c) - Quick call setup
- - Smart device pairing (groups mic + monitor by hardware)
- - One selection for both mic and system audio
- - Handles Bluetooth MAC normalization
-
-Devices cached in variables for future recordings.
-Can switch devices without restarting Emacs.
-
-*** DONE [#B] Improve error messages
-CLOSED: [2025-11-03 Sun]
-
-✅ Error messages now include:
-- Guidance to run `cj/recording-select-devices`
-- Clear indication when auto-detection fails
-- User-friendly prompts for manual selection
+** TODO [#B] Validate recording startup
-*** DONE [#B] Make device detection more flexible
-CLOSED: [2025-11-03 Sun]
-
-✅ Implemented multi-level fallback system:
-1. Auto-detect using pactl output parsing
-2. Prompt user to select manually if auto-detect fails
-3. Error with helpful guidance if user declines
-
-✅ Smart device grouping in `cj/recording-group-devices-by-hardware`:
-- Handles USB, PCI (built-in), and Bluetooth devices
-- Normalizes Bluetooth MAC addresses (colons ↔ underscores)
-- Assigns friendly names (e.g., "Built-in Laptop Audio", "Bluetooth Headset")
-- Filters incomplete devices (must have both mic and monitor)
-
-✅ Supports both PulseAudio and PipeWire (both use pactl).
-
-*** TODO [#B] Validate recording startup
Check process status after starting.
Parse ffmpeg output for errors.
Show actual ffmpeg command for debugging.
-** DONE [#C] Fix grammar checker performance (currently disabled)
-CLOSED: [2025-11-04 Mon]
-
-✅ **Installed and configured LanguageTool for comprehensive grammar checking**
-
-Replaced disabled grammar checker with on-demand LanguageTool integration:
-- Installed LanguageTool 6.6-2 from Arch repos (222MB)
-- Created wrapper script: scripts/languagetool-flycheck (Python 3)
-- Integrated with flycheck for on-demand checking via C-; ?
-- Removed proselint (redundant - LanguageTool catches more)
-- No performance impact: only runs when explicitly invoked
-- Installation instructions added to modules/flycheck-config.el commentary
-
-LanguageTool catches:
-- Real grammar errors (subject-verb agreement, tense, etc.)
-- Missing punctuation (commas, periods)
-- Common mistakes (could of → could have)
-- Style issues (redundant phrases, wordiness)
-
-Workflow: Open org/text/markdown file → press C-; ? → see errors in *Flycheck errors* buffer
-
-** DONE [#C] cj/flyspell-then-abbrev loses keybinding in scratch org-mode buffer
-CLOSED: [2025-11-08 Fri]
-
-✅ Fixed keybinding issue in org-mode buffers.
-
-**Problem:**
-1. Autoload cookies were just comments and never executed
-2. Org-mode was overriding C-' with org-cycle-agenda-files
-
-**Solution:**
-- Set keybindings directly when module loads (lines 239-240)
-- Explicitly override org-mode's C-' after org loads (lines 244-245)
-- Both C-' and C-c f now work correctly in all buffers including org-mode
-
-File modified: modules/flyspell-and-abbrev.el:235-251
-
-* Method 2: Stop Problems Before They Appear [4/8]
** TODO [#B] Write Complete ERT Tests for This Config [0/31]
+
Unit and Integration Tests should be added as subtasks below, marked done when complete.
*High-value test targets (no coverage, testable logic, daily use):*
-*** TODO custom-case — pure case conversion functions (upper/lower/title)
-*** TODO custom-datetime — date/timestamp insertion and formatting
-*** TODO host-environment — platform detection (env-macos-p, env-wayland-p, etc.)
-*** TODO hugo-config — draft toggle, slug generation, post template
-*** TODO org-capture-config — template building (relates to capture perf optimization)
-*** TODO modeline-config — custom segment construction
-*** TODO external-open — file-type detection and external app dispatch
-*** TODO reconcile-open-repos — dirty repo scanning logic
-*** TODO media-utils — URL download/play logic
-*** TODO org-config — org-mode utility functions
-*** TODO org-export-config — export helper functions
-*** TODO local-repository — package snapshot logic
-*** TODO show-kill-ring — kill ring display logic
-*** TODO system-commands — reboot/logout/system action functions
-*** TODO config-utilities — debug helper functions
+- [ ] custom-case — pure case conversion functions (upper/lower/title)
+- [ ] custom-datetime — date/timestamp insertion and formatting
+- [ ] host-environment — platform detection (env-macos-p, env-wayland-p, etc.)
+- [ ] hugo-config — draft toggle, slug generation, post template
+- [ ] org-capture-config — template building (relates to capture perf optimization)
+- [ ] modeline-config — custom segment construction
+- [ ] external-open — file-type detection and external app dispatch
+- [ ] reconcile-open-repos — dirty repo scanning logic
+- [ ] media-utils — URL download/play logic
+- [ ] org-config — org-mode utility functions
+- [ ] org-export-config — export helper functions
+- [ ] local-repository — package snapshot logic
+- [ ] show-kill-ring — kill ring display logic
+- [ ] system-commands — reboot/logout/system action functions
+- [ ] config-utilities — debug helper functions
*Modules with partial coverage (expand existing tests):*
-*** TODO org-agenda-config — caching/TTL logic untested (only build-list covered)
-*** TODO org-contacts-config — expand beyond capture/parse
-*** TODO prog-shell — expand beyond make-script-executable
-*** TODO ui-config — expand beyond buffer-status/cursor-color
-*** TODO org-refile-config — expand beyond build-targets
-*** TODO org-webclipper — expand beyond process (only 1 test file)
-*** TODO org-noter-config — expand beyond generate-notes/title-to-slug
-*** TODO browser-config — expand beyond current single test file
-*** TODO flycheck-config — expand beyond languagetool setup
-*** TODO org-drill-config — expand beyond first-function/font-switching
+- [ ] org-agenda-config — caching/TTL logic untested (only build-list covered)
+- [ ] org-contacts-config — expand beyond capture/parse
+- [ ] prog-shell — expand beyond make-script-executable
+- [ ] ui-config — expand beyond buffer-status/cursor-color
+- [ ] org-refile-config — expand beyond build-targets
+- [ ] org-webclipper — expand beyond process (only 1 test file)
+- [ ] org-noter-config — expand beyond generate-notes/title-to-slug
+- [ ] browser-config — expand beyond current single test file
+- [ ] flycheck-config — expand beyond languagetool setup
+- [ ] org-drill-config — expand beyond first-function/font-switching
*Lower priority (testable but less critical):*
-*** TODO chrono-tools — timer/clock functions
-*** TODO help-utils — search dispatch (arch-wiki, devdoc, tldr, wikipedia)
-*** TODO dirvish-config — wallpaper setter, custom functions
-*** TODO dwim-shell-config — shell command definitions
-*** TODO elfeed-config — podcast/feed helper functions
-*** TODO eww-config — browser helper functions
+- [ ] chrono-tools — timer/clock functions
+- [ ] help-utils — search dispatch (arch-wiki, devdoc, tldr, wikipedia)
+- [ ] dirvish-config — wallpaper setter, custom functions
+- [ ] dwim-shell-config — shell command definitions
+- [ ] elfeed-config — podcast/feed helper functions
+- [ ] eww-config — browser helper functions
** TODO [#B] Review all config and pull library functions into system-lib file
@@ -908,31 +167,12 @@ This makes them:
5. Document the purpose/scope of system-lib.el in its Commentary section
**Criteria for inclusion in system-lib.el:**
-- ✓ Pure utility functions (no side effects)
-- ✓ System-level queries (executable detection, path operations)
-- ✓ Platform-agnostic where possible
-- ✓ No dependencies on mode-specific functionality
-- ✗ NOT buffer/file operations (those stay in custom-buffer-file.el)
-- ✗ NOT user-facing commands (those stay in their domain modules)
-
-**Related Files:**
-- modules/system-lib.el (target file)
-- modules/host-environment.el (likely source)
-- modules/system-utils.el (likely source)
-- modules/config-utilities.el (check for candidates)
-- tests/test-system-lib-*.el (add tests for moved functions)
-
-**Related Docs:**
-- Recent refactoring: Created system-lib.el with cj/executable-exists-p
-- Testing guidance: ai-prompts/quality-engineer.org
-- V2MOM Method 2: Stop Problems Before They Appear (better organization)
-
-**Success Criteria:**
-- All generic system utilities consolidated in system-lib.el
-- Each function has comprehensive test coverage
-- No functionality broken (all tests pass)
-- Documentation explains purpose and scope of system-lib.el
-- Other modules properly require system-lib where needed
+- Pure utility functions (no side effects)
+- System-level queries (executable detection, path operations)
+- Platform-agnostic where possible
+- No dependencies on mode-specific functionality
+- NOT buffer/file operations (those stay in custom-buffer-file.el)
+- NOT user-facing commands (those stay in their domain modules)
** TODO [#C] Migrate from Company to Corfu
:PROPERTIES:
@@ -945,351 +185,19 @@ Complete config already exists in someday-maybe.org. Just needs to be executed.
Already using prescient with vertico. Extend to Corfu after migration.
-** DONE [#B] Move cj/log-silently to system-lib
-CLOSED: [2025-11-16 Sun 18:36]
-
-The `cj/log-silently` function is a generic utility for logging messages without
-displaying them in the echo area. It should be moved to system-lib.el for better
-organization and reusability across modules.
-
-**Current Problem:**
-- cj/log-silently is likely defined in a specific module
-- It's a generic logging utility that could be used by any module
-- Not easily discoverable for reuse
-- Doesn't follow the system-lib pattern we're establishing
-
-**What is cj/log-silently?**
-This function logs messages to the *Messages* buffer without interrupting the user
-by displaying them in the echo area (minibuffer). Useful for debugging and tracing
-code execution without breaking user flow.
-
-**Task:**
-1. **Find current location:**
- ```bash
- grep -rn "defun cj/log-silently" modules/
- ```
-
-2. **Review implementation:**
- - Check if it has dependencies on mode-specific functionality
- - Verify it's truly generic (should be)
- - Check for any callers that need updating
-
-3. **Move to system-lib.el:**
- - Cut from current location
- - Paste into system-lib.el
- - Add appropriate commentary/docstring
- - Ensure proper section organization
-
-4. **Update callers:**
- - Find all uses: `grep -rn "cj/log-silently" modules/`
- - Add `(require 'system-lib)` to any module that uses it
- - Verify no circular dependencies
-
-5. **Write tests:**
- Create `tests/test-system-lib-log-silently.el` with coverage for:
- - Normal cases: logging simple messages
- - Boundary cases: empty strings, very long messages, special characters
- - Error cases: nil input, non-string input
- - Verify output: check *Messages* buffer contains logged text
- - Verify silence: ensure nothing appears in echo area
-
-**Expected Signature:**
-```elisp
-(defun cj/log-silently (format-string &rest args)
- "Log a message to *Messages* buffer without displaying in echo area.
-FORMAT-STRING and ARGS work like `message' but output is not shown to user."
- (let ((inhibit-message t))
- (apply #'message format-string args)))
-```
-
-**Related Files:**
-- modules/system-lib.el (destination)
-- Current module where cj/log-silently lives (TBD - find it)
-- All modules that call cj/log-silently (update requires)
-- tests/test-system-lib-log-silently.el (NEW - create this)
-
-**Related Docs:**
-- System-lib refactoring initiative (previous TODO)
-- quality-engineer.org (testing guidance)
-- Recent refactoring: moved cj/executable-exists-p to system-lib
-- V2MOM Method 2: Stop Problems Before They Appear (better organization)
-
-**Success Criteria:**
-- cj/log-silently moved to system-lib.el
-- All callers updated with proper requires
-- Comprehensive test coverage (normal/boundary/error cases)
-- All existing tests still pass (no regressions)
-- Function works identically to before
-- Well-documented in system-lib.el
-
-**Testing:**
-1. Run all tests before move (baseline)
-2. Move function and update requires
-3. Run all tests after move (verify no breakage)
-4. Run new cj/log-silently tests (verify behavior)
-5. Test in real usage (logging works, messages not shown)
-
-**Note:**
-Priority [#B] because this is part of the larger system-lib consolidation effort
-(separate TODO). Logging utilities are commonly used, so centralizing them improves
-discoverability and encourages consistent logging patterns across the codebase.
-
-** DONE [#C] Switch to mood-line (actually: built custom modeline)
-CLOSED: [2025-11-03 Sun]
-
-✅ **Built custom modeline (better than mood-line)**
-
-Went beyond mood-line and created a fully custom modeline using only built-in
-Emacs functionality to avoid native-compilation issues. Features:
-
-**Architecture:**
-- Named segment system using defvar-local (easy to reorder)
-- Emacs 30 built-in right-alignment (mode-line-format-right-align)
-- All segments marked as risky-local-variable for proper evaluation
-
-**Interactive Features:**
-- Color-coded buffer names (green=writeable, red=read-only, gold=overwrite)
-- VC branch with git symbol () and state-based coloring
-- Mouse click handlers: buffer name (prev/next), branch (vc-diff), mode (describe-mode)
-- Help-echo tooltips on all segments
-- String truncation for narrow windows (< 100 chars wide)
-- Active-window-only display for branch and misc-info (less clutter)
-
-**Layout:**
-- Left: Major mode, buffer name, position (L:# C:#)
-- Right: Git branch, chime notifications
-
-**Bug Fixes:**
-- Disabled async native compilation (prevented "Selecting deleted buffer" errors)
-- Fixed difftastic loading (:demand → :defer)
-- Abstracted buffer status colors to user-constants.el
-
-Inspired by Prot's modeline design. See commit c0c4b17.
-
-** DONE [#C] Remove deprecated tree-sitter package (rely on treesit-auto)
-CLOSED: [2025-11-03 Sun]
-
-✅ Removed deprecated tree-sitter package from modules/prog-general.el
-- Deleted `(use-package tree-sitter)` on line 97
-- Now relies solely on Emacs 29+ built-in treesit with treesit-auto
-- treesit-auto continues to manage tree-sitter grammars automatically
-- No functionality lost, cleaner dependency tree
-
-** DONE [#C] Add org-appear (show emphasis markers only when point is on them)
-CLOSED: [2025-11-03 Sun]
-
-✅ Added org-appear package to modules/org-config.el
-- Shows emphasis markers (* / _) only when cursor is on them
-- Also shows link markup and sub/superscripts when editing
-- Changed org-fontify-emphasized-text from nil to t (line 75)
-- Updated comment on line 71 to reference org-appear
-- Cleaner editing experience while maintaining visual clarity
-
-* Method 3: Make *Fixing* Emacs Frictionless [0/9]
-** DONE [#A] Write tests for cj/make-script-executable (suspected broken)
-CLOSED: [2025-11-11 Tue]
-
-The `cj/make-script-executable` function automatically makes shell scripts executable
-when they have a shebang, but has no test coverage. **Suspected to be broken/not working.**
-This is a critical function that modifies file permissions and runs on every save.
-
-**Function Location:**
-modules/prog-shell.el:158-167
-
-**Why This Matters:**
-1. Runs automatically on after-save-hook in shell-script-mode (high frequency)
-2. Modifies file permissions (security-relevant)
-3. If broken, scripts won't become executable automatically
-4. No test coverage means bugs go undetected
-
-**Investigation First:**
-1. Test manually: Create test.sh with `#!/bin/bash`, save, check if executable
-2. Check if function is actually hooked to after-save-hook
-3. Verify conditions in function logic are correct
-4. Look for any error messages in *Messages* buffer
-
-**Then Write Tests:**
-Following quality-engineer.org patterns:
-- Normal cases: Various shebangs (bash, python, ruby, etc.)
-- Boundary cases: Shebang with spaces, not at start, already executable
-- Error cases: No file, read-only filesystem, permission errors
-
-**Estimated Work:**
-- Manual testing: 15 minutes
-- Writing comprehensive tests: 2-3 hours
-- ~20-25 tests total
-
-**Success Criteria:**
-- Confirm function works or identify bug
-- Comprehensive test coverage
-- Tests document expected behavior
-- Can refactor safely with tests as safety net
-
-Priority [#B] because if broken, it's a daily workflow issue (scripts don't auto-execute).
-Moved from inbox 2025-11-11.
-
-** DONE [#A] Fix difftastic integration - not showing semantic diffs (just unified diff)
-CLOSED: [2025-11-11 Tue]
-
-Difftastic was marked as "integrated" but diffs in magit and custom-buffer-file.el look
-identical to standard unified diffs. **Likely not actually using difftastic** - probably
-falling back to git diff or missing a configuration switch.
-
-**Problem:**
-Two places where difftastic should work but doesn't:
-1. **Magit diffs** - Should show semantic diffs with D/S keybindings, but looks like unified diff
-2. **Buffer diff** (custom-buffer-file.el) - cj/diff-buffer-with-file should use difftastic but looks like unified diff
-
-**Investigation:**
-1. Check if difftastic binary actually gets called:
- - Test: `difft --version` (verify binary exists)
- - Test: `difft file1.el file2.el` manually to see what output looks like
- - Should show syntax-aware, tree-based diff (very different from unified)
-
-2. Review vc-config.el difftastic setup (lines ~176-190):
- - Is difftastic.el package loaded? (check with `M-x package-list-packages`)
- - Are keybindings actually bound? (check magit-diff-mode-map)
- - Is there a configuration switch we're missing?
-
-3. Check custom-buffer-file.el:
- - Claims to use ediff (line 554-565), not difftastic
- - Confusion: Is it supposed to use difftastic or ediff?
- - If ediff, that's different tool (interactive split-screen, not semantic)
-
-**Possible Issues:**
-A. difftastic.el not actually loaded (:defer preventing it)
-B. Missing transient menu configuration for magit
-C. Need to enable difftastic-mode explicitly
-D. Keybindings shadowed by other bindings
-E. ANSI color codes not rendering (looks wrong but is difftastic)
-
-**Expected Behavior:**
-Difftastic output should look VERY different from unified diff:
-- Tree-based syntax matching
-- Side-by-side or structured format
-- Language-aware (knows it's elisp/org/etc)
-- Shows matched nodes, not just line changes
-
-**Next Steps:**
-1. Run difft manually on two .el files to see expected output
-2. Try calling difftastic functions directly: `M-x difftastic-magit-diff`
-3. Check *Messages* for errors when using D/S in magit
-4. Review difftastic.el documentation for required configuration
-
-**Related Files:**
-- modules/vc-config.el (difftastic config)
-- modules/custom-buffer-file.el (buffer diff - might be ediff, not difftastic?)
-- Binary: /usr/bin/difft
-
-**Success Criteria:**
-- Diffs in magit show obvious semantic/structural differences
-- Output clearly different from unified diff
-- Can visually identify it's difftastic (not git diff)
-- Documented how to use and what to expect
-
-Priority [#B] because if not working, we're not getting the benefit of difftastic integration.
-Moved from inbox 2025-11-11.
-
-** TODO [#B] Build debug-profiling.el module
-
-Reusable profiling infrastructure for any future performance work.
-** TODO [#C] Evaluate Buttercup for integration tests
-** TODO [#B] Add project-aware ERT test isolation when switching projects
-
-When switching between elisp projects (e.g., emacs.d to chime.el), previously loaded
-ERT tests remain in memory causing confusion and wrong tests to run.
-
-**Problem:**
-- ERT tests globally registered in Emacs session
-- `M-x ert RET t RET` runs ALL loaded tests from ALL projects
-- Can accidentally run emacs.d tests when working on chime.el
-- Current workaround: restart Emacs (loses session state)
-
-**Solution:**
-Create `cj/ert-clear-tests` and `cj/ert-run-current-project-tests`:
-- Clear tests when switching projects (hook into project-switch)
-- Use test name prefixes to selectively clear (cj/ vs chime-)
-- Only run current project's tests
-
-**Success Criteria:**
-- Switch projects → old tests cleared
-- Only current project's tests run with `M-x ert`
-- Works with both interactive and batch runs
-
-Priority [#B] because affects daily workflow when working on multiple elisp projects.
-Moved from inbox 2025-11-11.
-
-** DONE [#B] Remove ANSI color codes from Makefile - breaks test output readability
-CLOSED: [2025-11-11 Tue]
-
-ANSI color codes render incorrectly in some terminals, making test output unreadable.
-Can see it's colored red, but can't read what the actual error message says due to
-escape code littering throughout the text. Blocks debugging.
-
-**Problem:**
-- Makefile uses variables like `COLOR_GREEN`, `COLOR_RED`, `COLOR_BLUE`
-- These insert ANSI escape codes like `\033[0;32m` into output
-- Makes output harder to read, especially in logs or when piped
-- Color codes don't work well in all terminals
-- Unnecessary complexity
-
-**Proposed Solution:**
-Replace color codes with simple text markers:
-- `✓` (checkmark) for success - KEEP THIS
-- `✗` (x mark) for failure - KEEP THIS
-- `[i]` for informational messages
-- Remove color entirely, rely on symbols alone
-
-**Examples:**
-Current:
-```
-\033[0;32m✓ All unit tests passed\033[0m
-\033[0;31m✗ 18 unit test file(s) failed\033[0m
-\033[0;34mRunning unit tests...\033[0m
-```
-
-Proposed:
-```
-✓ All unit tests passed
-✗ 18 unit test file(s) failed
-[i] Running unit tests...
-```
-
-**Implementation:**
-1. Find all `COLOR_*` variables in Makefile
-2. Replace colored text with plain text + symbols
-3. Remove color variable definitions
-4. Test that output is still clear and readable
-
-**Related Files:**
-- Makefile (all COLOR_ variables and usage)
-
-**Success Criteria:**
-- No ANSI escape codes in Makefile
-- Output still clear and readable
-- Uses text symbols (✓, ✗, [i]) appropriately
-- Simpler, cleaner Makefile
-- Test output works in any terminal/CI environment
-
-**Note:**
-Priority [#B] because it improves readability and maintainability. Not urgent,
-but makes the codebase cleaner and more portable.
-
-** TODO [#C] Build localrepo out (package snapshot system)
+** TODO [#C] Build localrepo and document limitations
Repeatable installs and safe rollbacks.
-*** TODO [#C] Document localrepo limitations (treesitter grammars not included)
-
.localrepo only contains packages from package.el archives.
Treesitter grammars are downloaded separately by treesit-auto on first use.
For true offline reproducibility, need to cache treesitter grammars separately.
-** TODO [#C] Integrate Buttercup (behavior-driven integration tests)
+** TODO [#C] Evaluate and integrate Buttercup for behavior-driven integration tests
Complex workflow testing capability.
-** TODO [#D] Optimize lorem-optimum performance for faster text generation
+** TODO [#D] Optimize lorem-optimum performance and liber-primus.txt size
Lorem-optimum text generation is generally slow but doesn't completely break workflow.
Two benchmark tests were disabled (marked :slow) because they take MINUTES instead of seconds.
@@ -1310,129 +218,32 @@ Two benchmark tests were disabled (marked :slow) because they take MINUTES inste
- tests/test-lorem-optimum-benchmark.el (tests disabled with :tags '(:slow))
- liber-primus.txt (corpus file, may need size optimization)
-**Success Criteria:**
-- Text generation completes in reasonable time
-- Benchmark tests run in < 5 seconds
-- Tests can be re-enabled without blocking test suite
-
-Priority [#D] because it's not breaking workflow, just slower than ideal.
-
-
-*** TODO [#D] Optimize size of liber-primus.txt for lorem-optimum and investigate launch notices
-
-The liber-primus.txt file may be too large for optimal lorem-optimum performance,
-causing slow random text generation or excessive memory usage. Additionally, there
-are notices appearing in the *Messages* buffer during Emacs launch that need investigation.
-
-**Primary Problem:**
-- liber-primus.txt might be too large for efficient text generation
-- lorem-optimum may be slow when selecting random text from large corpus
-- File size could be causing memory or performance issues
-- Impact on startup time or buffer creation unknown
+** TODO [#B] Build debug-profiling.el module
-**Secondary Problem:**
-- *Messages* buffer shows notices during Emacs launch
-- May be related to lorem-optimum, liber-primus, or unrelated issues
-- Need to identify source and severity of notices
+Reusable profiling infrastructure for any future performance work.
-**Investigation:**
+** TODO [#B] Add project-aware ERT test isolation when switching projects
-1. **Check current file size:**
- ```bash
- ls -lh liber-primus.txt
- wc -l liber-primus.txt
- wc -w liber-primus.txt
- ```
-
-2. **Review lorem-optimum configuration:**
- - Find lorem-optimum module: `grep -r "lorem-optimum" modules/`
- - Check how liber-primus.txt is loaded
- - Look for performance issues in implementation
- - Check if entire file is loaded into memory
-
-3. **Test performance with current file:**
- ```elisp
- (benchmark-run 100
- (lorem-ipsum-insert-paragraphs 1))
- ```
- - Measure baseline performance
- - Note memory usage
-
-4. **Investigate Messages buffer notices:**
- - Launch Emacs with `emacs --debug-init`
- - Check *Messages* buffer immediately after startup
- - Search for lorem, liber-primus, or warning keywords
- - Note timestamps and context
-
-5. **Identify notices source:**
- - Could be from lorem-optimum loading
- - Could be file permissions warnings
- - Could be encoding issues
- - Could be unrelated initialization messages
-
-**Possible Solutions:**
-
-1. **Reduce file size** (if too large):
- - Keep most meaningful/interesting sections
- - Remove repetitive content
- - Target size: 50-100KB (fast loading, sufficient variety)
- - Preserve character of cryptic/cipher text
-
-2. **Optimize lorem-optimum loading** (if implementation issue):
- - Lazy load: don't read file until first use
- - Sample lines: don't load entire file
- - Cache in memory: read once, reuse
- - Stream reading: read chunks as needed
-
-3. **Fix launch notices** (if errors/warnings):
- - Fix source of warnings
- - Silence benign notices
- - Add proper error handling
- - Document expected behavior
-
-**Testing:**
-1. Note baseline: file size, performance, messages
-2. Apply optimization (file size or code)
-3. Measure improvement:
- - File size reduced?
- - Performance improved?
- - Messages cleaned up?
-4. Verify text generation still works
-5. Check variety/quality of generated text
+When switching between elisp projects (e.g., emacs.d to chime.el), previously loaded
+ERT tests remain in memory causing confusion and wrong tests to run.
-**Related Files:**
-- liber-primus.txt (the text corpus file)
-- modules/lorem-optimum.el or similar (lorem generation module)
-- init.el (loading sequence, Messages source)
-- tests/test-lorem-optimum-*.el (performance/benchmark tests)
+**Problem:**
+- ERT tests globally registered in Emacs session
+- `M-x ert RET t RET` runs ALL loaded tests from ALL projects
+- Can accidentally run emacs.d tests when working on chime.el
+- Current workaround: restart Emacs (loses session state)
-**Related Docs:**
-- DONE task at line 68-96: "Review lorem-optimum benchmark tests and fix"
-- Failed benchmark tests may be related to this issue
-- V2MOM Method 1: Frictionless (fast text generation)
-- V2MOM Method 2: Stop Problems Before They Appear (clean Messages)
+**Solution:**
+Create `cj/ert-clear-tests` and `cj/ert-run-current-project-tests`:
+- Clear tests when switching projects (hook into project-switch)
+- Use test name prefixes to selectively clear (cj/ vs chime-)
+- Only run current project's tests
**Success Criteria:**
-- liber-primus.txt optimized to reasonable size (<100KB ideal)
-- lorem-optimum generates text quickly (<100ms for paragraph)
-- No unnecessary notices in *Messages* during launch
-- Text generation still produces varied, interesting output
-- Benchmark tests pass (after fixing per separate TODO)
-- Documented optimal file size and loading strategy
-
-**Benchmark Target:**
-- Text generation: <100ms for 1 paragraph
-- File loading: <50ms at startup (if not lazy loaded)
-- Memory usage: Reasonable for file size
-- No degradation from current working state
-
-**Note:**
-Priority [#B] because performance impacts daily workflow (lorem text generation
-used frequently for testing) and clean *Messages* buffer is important for catching
-real issues during startup. This ties into fixing the 2 failed benchmark tests
-(separate TODO at line 68-96).
-
-* Method 4: Contribute to the Emacs Ecosystem [0/4]
+- Switch projects -> old tests cleared
+- Only current project's tests run with `M-x ert`
+- Works with both interactive and batch runs
+
** TODO [#C] Integrate undercover.el for test coverage
Measure and track test coverage over time.
@@ -1449,22 +260,6 @@ Catch packaging issues automatically.
Zero-config CI for Emacs packages.
-* Method 5: Be Kind To Your Future Self [1/2]
-** DONE [#C] Add transcription workflow
-CLOSED: [2025-11-12 Wed 02:41]
-:PROPERTIES:
-:COMPLETE_CONFIG: [[file:docs/someday-maybe.org::2][todo.org:2-99]]
-:END:
-
-Complete code already exists in someday-maybe.org. Need today and recurring.
-
-** DONE [#A] Implement org-reveal presentation workflow
-CLOSED: [2026-02-14 Fri]
-
-Created org-reveal-config.el module with ox-reveal integration for offline,
-self-contained reveal.js presentations. Keybindings under C-; p prefix.
-Removed pandoc-based reveal.js export from org-export-config.el.
-
** TODO [#B] Create custom dupre reveal.js theme
Create a custom reveal.js CSS theme using colors from themes/dupre-palette.el.
@@ -1477,7 +272,6 @@ yasnippet is configured in prog-general.el, but no custom snippets directory or
snippet files exist. Investigate whether snippets should be created (e.g., org
structure templates for reveal.js headers, blog post front matter, etc.).
-* Method 6: Develop Disciplined Engineering Practices [1/3]
** TODO [#C] Track current metrics baseline
- [ ] Measure current startup time (time emacs --eval '(save-buffers-kill-emacs)')
@@ -1488,58 +282,6 @@ structure templates for reveal.js headers, blog post front matter, etc.).
Can't research next thing until current thing is implemented.
-** DONE [#A] First weekly triage by Sunday (establish habit)
-CLOSED: [2025-11-12 Wed 02:41] SCHEDULED: <2025-11-03 Sun>
-
-Review this inbox, cancel stale items, keep < 20 active. Track in calendar.
-
-* Emacs Config Inbox
-** VERIFY [#B] Continue org-noter custom workflow implementation (IN PROGRESS)
-
-Continue debugging and testing the custom org-noter workflow from 2025-11-21 session.
-This is partially implemented but has known issues that need fixing before it's usable.
-
-**Last worked on:** 2025-11-21
-**Current status:** Implementation complete but has bugs, needs testing
-
-**Known Issues to Fix:**
-
-1. **Double notes buffer appearing when pressing 'i' to insert note**
- - When user presses 'i' in document to insert a note, two notes buffers appear
- - Expected: single notes buffer appears
- - Need to debug why the insert-note function is creating duplicate buffers
-
-2. **Toggle behavior refinement needed**
- - The toggle between document and notes needs refinement
- - May have edge cases with window management
- - Need to test various scenarios
-
-**Testing Needed:**
-
-1. **EPUB files** - Test with EPUB documents (primary use case)
-2. **Reopening existing notes** - Verify it works when notes file already exists
-3. **Starting from notes file** - Test opening document from an existing notes file
-4. **PDF files** - Verify compatibility with PDF workflow
-5. **Edge cases:**
- - Multiple windows open
- - Splitting behavior
- - Window focus after operations
-
-**Implementation Files:**
-- modules/org-noter-config.el - Custom workflow implementation
-- Contains custom functions for document/notes toggling and insertion
-
-**Context:**
-This custom workflow is designed to make org-noter more ergonomic for Craig's reading/annotation
-workflow. It simplifies the toggle between document and notes, and streamlines note insertion.
-The core functionality is implemented but needs debugging before it's production-ready.
-
-**Next Steps:**
-1. Debug the double buffer issue when pressing 'i'
-2. Test all scenarios listed above
-3. Refine toggle behavior based on testing
-4. Document the final keybindings and workflow
-
** TODO [#D] Add status dashboard for dwim-shell-command processes
Create a command to show all running dwim-shell-command processes with their status.
@@ -1551,39 +293,10 @@ Currently, there's no unified view of multiple running extractions/conversions.
- On completion: buffer renamed to `*Extract audio done*` or `*Extract audio error*`
- No way to see all running processes at once
-**Implementation approaches:**
-
-1. **Use existing process list (simplest):**
- - Enhance `M-x list-processes` output filtering
- - Create wrapper command that filters to dwim-shell processes only
- - Pro: Uses built-in functionality
- - Con: Generic process list, not tailored
-
-2. **Custom status buffer:**
- - Create command `dwim-shell-commands-status` or similar
- - Access `dwim-shell-command--commands` variable (tracks all running commands)
- - Display in custom buffer with:
- - Command name
- - Files being processed
- - Progress/status
- - Time running
- - Allow actions: view buffer, kill process
- - Pro: Tailored UI, more useful information
- - Con: More code to maintain
-
-3. **Mode-line indicator:**
- - Show count of running dwim commands in mode-line
- - Click to open status buffer
- - Pro: Always visible, lightweight
- - Con: Limited information at a glance
-
**Recommended approach:**
-Start with option 2 (custom status buffer) that reads `dwim-shell-command--commands`.
+Custom status buffer that reads `dwim-shell-command--commands`.
Can add mode-line indicator later as enhancement.
-**Files to create/modify:**
-- modules/dwim-shell-config.el - add status command
-
** TODO [#C] Create print function for dirvish bound to uppercase P
Add a print function that works on printable files (PDF, txt, org, etc.) and bind it to uppercase P in dirvish-mode. Should detect file type and use appropriate print command (lpr for text files, print dialog for PDFs, etc.).
@@ -1606,20 +319,10 @@ Need to either:
- modules/flycheck-config.el (customize prefix/indicator)
- modules/modeline-config.el (add to mode-line-format)
-**Emoji Options:**
-- Prefix: 🪰 (fly), 🐛 (bug), ✓ (check), ⚠ (warning), 🔍 (magnifier)
-- Success: ✓, ✅, 🟢, ✨, 💯
-
**Recommended Approach:**
Option 4 (Hybrid) from spec - customize flycheck variables + add to modeline.
Simple, maintainable, respects flycheck's built-in logic.
-**Next Steps:**
-1. Review spec document and choose emoji combination
-2. Add customization to flycheck-config.el
-3. Add to modeline-config.el mode-line-format
-4. Test in sh-mode and emacs-lisp-mode buffers
-
** TODO [#C] Investigate TRAMP/dirvish showing question marks for file dates
Remote directories in dirvish show "?" instead of actual modification dates.
@@ -1636,18 +339,12 @@ Tried several approaches without success - needs deeper investigation.
- Could be an Emacs 29/30 + TRAMP + dirvish interaction issue
- May require changes to how dirvish renders the file-size attribute on remote
-**Resources:**
-- https://github.com/alexluigit/dirvish/discussions/124 (related TRAMP issues)
-- https://github.com/alexluigit/dirvish/blob/main/docs/CUSTOMIZING.org (TRAMP section)
-
**Files involved:**
- modules/tramp-config.el
- modules/dirvish-config.el
-**Workaround:**
-Use regular dired for remote directories if timestamps are needed.
+** TODO [#B] Review and rebind M-S- keybindings
-* TODO [#B] Review and rebind M-S- keybindings
Changed from M-uppercase to M-S-lowercase for terminal compatibility.
These may override useful defaults - review and pick better bindings:
- M-S-b calibredb (was overriding backward-word)
@@ -1669,3 +366,5 @@ These may override useful defaults - review and pick better bindings:
- M-S-w wttrin (was overriding kill-ring-save)
- M-S-y yank-media (was overriding yank-pop)
- M-S-z undo-kill-buffer (was overriding zap-to-char)
+
+* Emacs Resolved
diff --git a/v2mom.org b/v2mom.org
new file mode 100644
index 00000000..27b5e366
--- /dev/null
+++ b/v2mom.org
@@ -0,0 +1,1671 @@
+#+TITLE: Emacs Config V2MOM and Tasks
+#+AUTHOR: Craig Jennings
+#+DATE: 2025-10-31
+#+FILETAGS: :v2mom:active:
+
+* Instructions
+
+This inbox contains ONLY tasks that serve the V2MOM vision. Before adding any task here, ask:
+1. Does it serve the Vision?
+2. Does it align with the Values?
+3. Is it addressed in the Methods?
+4. Does it overcome an Obstacle?
+5. Does it improve a Metric?
+
+If the answer is "no" to all five → DON'T ADD IT.
+
+V2MOM is located at: [[file:docs/emacs-config-v2mom.org][emacs-config-v2mom.org]]
+Research/ideas that don't serve vision: [[file:docs/someday-maybe.org][someday-maybe.org]]
+
+* Method 1: Make Using Emacs Frictionless [16/24]
+** VERIFY [#B] Fix org-noter (reading/annotation workflow currently "so painful")
+
+High priority - daily pain point.
+
+** VERIFY [#B] Fix mail attachment workflow (currently awkward)
+
+Daily workflow improvement.
+
+** DONE [#B] Optimize org-agenda performance using built-in profiler
+
+THE BOTTLENECK. Currently 30+ seconds, target < 5 seconds.
+Use M-x profiler-start before Method 3 debug-profiling.el is built.
+
+** TODO [#B] Optimize org-capture target building performance
+
+15-20 seconds every time capturing a task (12+ times/day).
+Major daily bottleneck - minutes lost waiting, plus context switching cost.
+
+** TODO [#C] Finish terminal GPG pinentry configuration
+
+Continue work on terminal-mode GPG passphrase prompts (loopback mode).
+Branch: terminal-pinentry
+
+Changes in progress (modules/auth-config.el):
+- Use epa-pinentry-mode 'loopback in terminal
+- Use external pinentry (pinentry-dmenu) in GUI
+- Requires env-terminal-p from host-environment module
+
+** DONE [#C] Verify format-buffer hands off to shfmt in shell scripts
+
+Need to verify that the format-buffer command correctly delegates to shfmt when
+formatting shell scripts. May not be configured or may use wrong formatter.
+
+**Problem:**
+- Unknown if format-buffer works in shell-script-mode
+- May not be using shfmt (should use shfmt for shell scripts)
+- May be using a different formatter (or no formatter)
+- Need to verify configuration and test manually
+
+**Investigation:**
+1. Find format-buffer implementation:
+ - Search for defun format-buffer in modules/
+ - Check if it's in prog-general.el or separate module
+ - Review how it selects formatters per mode
+2. Check shfmt configuration:
+ - Is shfmt installed? `which shfmt`
+ - Is shfmt configured for shell-script-mode?
+ - What are the shfmt command-line arguments?
+3. Test manually:
+ - Create test shell script with bad formatting
+ - Run format-buffer command
+ - Verify it uses shfmt (not something else)
+ - Check formatted output is correct
+
+**Expected Behavior:**
+1. In shell-script-mode buffer
+2. Run format-buffer (or whatever the command is)
+3. Should invoke shfmt to format the buffer
+4. Output should be properly formatted shell code
+5. Should preserve shebang and script functionality
+
+**Possible Issues:**
+
+A. **shfmt not installed**
+ - Check: `pacman -Q shfmt` or `which shfmt`
+ - Install if missing: `sudo pacman -S shfmt`
+
+B. **format-buffer not configured for shell**
+ - May only work for elisp/python/etc.
+ - Need to add shell-script-mode configuration
+ - Need to specify shfmt command
+
+C. **Wrong formatter used**
+ - May be using bashfmt, beautysh, or other tool
+ - Should specifically use shfmt (preferred)
+
+D. **format-buffer doesn't exist**
+ - May be using different command name
+ - Check for format-all, apheleia, or custom function
+
+**Manual Test:**
+Create test file:
+```bash
+#!/bin/bash
+# Poorly formatted script
+if [ -f "test.txt" ];then
+echo "found"
+else
+ echo "not found"
+fi
+for i in 1 2 3;do echo $i;done
+```
+
+Expected after shfmt:
+```bash
+#!/bin/bash
+# Poorly formatted script
+if [ -f "test.txt" ]; then
+ echo "found"
+else
+ echo "not found"
+fi
+for i in 1 2 3; do
+ echo $i
+done
+```
+
+**Related Commands to Check:**
+- format-buffer
+- format-all-buffer
+- apheleia-format-buffer
+- Custom cj/format-buffer
+
+**Related Files:**
+- modules/prog-general.el (likely location of format-buffer)
+- modules/prog-shell.el (shell-specific config)
+- Check for apheleia or format-all package config
+
+**Related Docs:**
+- shfmt documentation: https://github.com/mvdan/sh
+- format-all or apheleia package docs (whichever is used)
+- V2MOM Method 1: Frictionless (formatting should just work)
+
+**Success Criteria:**
+- format-buffer (or equivalent) command exists
+- Works in shell-script-mode buffers
+- Uses shfmt as the formatter
+- Produces correctly formatted shell code
+- Doesn't break script functionality
+- Documented what command to use and how it works
+
+**If It Doesn't Work:**
+1. Install shfmt: `sudo pacman -S shfmt`
+2. Configure formatter (apheleia or format-all):
+ ```elisp
+ ;; Example configuration
+ (add-to-list 'apheleia-formatters
+ '(shfmt . ("shfmt" "-i" "2" "-ci")))
+ (add-to-list 'apheleia-mode-alist
+ '(shell-script-mode . shfmt))
+ ```
+3. Test again
+4. Document in prog-shell.el
+
+**Note:**
+Priority [#C] because formatting is nice-to-have. Can format manually with shfmt
+if needed. Low priority but good for maintaining code quality in shell scripts.
+
+Normal case: File with #!/bin/bash at start should get +x permission."
+ (let ((test-file (make-temp-file "test-script-" nil ".sh")))
+ (unwind-protect
+ (progn
+ ;; Write shebang to file
+ (with-temp-file test-file
+ (insert "#!/bin/bash\necho hello\n"))
+ ;; Remove execute permission
+ (set-file-modes test-file #o644)
+ (should-not (file-executable-p test-file))
+ ;; Open file and trigger function
+ (with-current-buffer (find-file-noselect test-file)
+ (cj/make-script-executable)
+ (kill-buffer))
+ ;; Verify file is now executable
+ (should (file-executable-p test-file)))
+ (delete-file test-file))))
+```
+
+**Related Files:**
+- modules/prog-shell.el:158-167 (function to test)
+- tests/test-prog-shell-make-script-executable.el (NEW - create this)
+- ai-prompts/quality-engineer.org (testing guidance)
+
+**Related Docs:**
+- quality-engineer.org: File system testing best practices
+- Recent test examples: test-custom-buffer-file-*.el (file operations)
+- Emacs manual: File permissions and file-modes function
+
+**Success Criteria:**
+- Comprehensive test file covering all normal/boundary/error cases
+- All tests pass on Linux
+- Tests properly clean up temp files
+- Tests verify actual file permission changes
+- Tests verify message output
+- No false positives (making non-script files executable)
+- No false negatives (missing files that should be executable)
+- Tests document expected behavior (serve as specification)
+
+**Estimated Tests:**
+- 6-8 normal cases (different shebangs)
+- 8-10 boundary cases (edge conditions)
+- 5-6 error cases (failure handling)
+- Total: ~20-25 tests
+
+**Note:**
+Priority [#B] because this function runs on every save in shell-script-mode and
+modifying file permissions incorrectly could cause security issues or workflow
+problems. Needs testing before any refactoring or changes.
+
+** VERIFY [#C] Fix EMMS keybinding inconsistency with other buffers
+
+EMMS keybindings conflict with standard buffer keybindings, causing mistypes.
+Results in accidental destructive actions (clearing buffers), requires undo + context switch.
+Violates Intuitive value - muscle memory should help, not hurt.
+
+** DONE [#D] Frequently used org-mode keybindings under C-; o
+
+Add quick access keybindings for common org commands (org-table, org-reveal, etc.) under C-; o.
+Makes org-mode operations more frictionless.
+Moved from inbox 2025-11-07.
+
+** DONE [#A] Music player is broken - mpd/mopidy need replacement
+CLOSED: [2025-11-16 Sun 18:35] SCHEDULED: <2025-11-15 Fri>
+
+music-config.el integration with mpd and mopidy is broken. Need to migrate to
+a different music player solution. Investigate alternatives:
+- emms with VLC/mpv backend
+- bongo player
+- Simple mpv integration
+- Other lightweight music player packages
+
+** DONE [#A] Fix recording workflow - phone call audio not captured (44 dB volume loss)
+CLOSED: [2025-11-14 Thu]
+
+✅ **Fixed by replacing amerge+pan with amix FFmpeg filter**
+
+**Problem:**
+On recorded calls, only one side was captured (user's microphone), not the other person's voice.
+Phone call audio was too quiet to transcribe (44 dB volume loss).
+
+**Root Cause:**
+FFmpeg's `amerge+pan` filter combination caused massive volume loss when mixing microphone
+and system monitor inputs. The `pan` filter reduced volume by 50% and `amerge` had issues
+with PulseAudio/PipeWire compatibility.
+
+**Solution:**
+Replaced `amerge=inputs=2[merged];[merged]pan=mono|c0=0.5*c0+0.5*c1` with `amix=inputs=2:duration=longest`
+filter. The `amix` filter properly mixes inputs without volume loss.
+
+**Changes Made:**
+- Changed FFmpeg filter from `amerge+pan` to `amix` (modules/video-audio-recording.el:513)
+- Increased default system volume from 0.5 to 2.0 (modules/video-audio-recording.el:76)
+- Added diagnostic tool `C-; r w` to show active audio playback
+- Created integration test with real voice recording
+- Fixed batch mode compatibility for tests
+
+**Results:**
+- Volume improved from -66.2 dB to -21.5 dB (44 dB improvement)
+- Test transcription: 100% accurate ("Can you hear me? Testing, one, two, three.")
+- Phone calls now capture both sides correctly
+
+**Testing:**
+Automated integration test verifies monitor capture works with perfect transcription.
+** DONE [#A] Fix Google Calendar password prompts every 15 minutes
+CLOSED: [2025-11-11 Mon]
+
+✅ **Fixed oauth2-auto caching bug**
+
+**Root Cause:**
+oauth2-auto.el version 20250624.1919 had a bug on line 206 that completely
+disabled its internal token cache with `or nil`. This forced every org-gcal
+sync to decrypt oauth2-auto.plist from disk, triggering GPG passphrase prompts
+every ~15 minutes.
+
+**The Bug:**
+```elisp
+;; Line 201-213 in oauth2-auto.el (BEFORE fix)
+(defun oauth2-auto--plstore-read (username provider)
+ "Read the data for USERNAME and PROVIDER from the cache, else from plstore."
+ (let ((id (oauth2-auto--compute-id username provider)))
+ ; Assume cache is invalidated. FIXME
+ (or nil ;(gethash id oauth2-auto--plstore-cache) ;; BUG: cache disabled!
+ (let ((plstore (plstore-open oauth2-auto-plstore)))
+ ...))))
+```
+
+**The Fix:**
+Enabled the internal hash-table cache by removing `or nil`:
+```elisp
+;; Line 201-213 in oauth2-auto.el (AFTER fix)
+(defun oauth2-auto--plstore-read (username provider)
+ "Read the data for USERNAME and PROVIDER from the cache, else from plstore."
+ (let ((id (oauth2-auto--compute-id username provider)))
+ ;; FIXED: Enable cache to prevent repeated GPG passphrase prompts
+ (or (gethash id oauth2-auto--plstore-cache) ;; Cache now works!
+ (let ((plstore (plstore-open oauth2-auto-plstore)))
+ ...))))
+```
+
+**What Changed:**
+1. Modified elpa/oauth2-auto-20250624.1919/oauth2-auto.el:201-213
+2. Removed `or nil` that disabled cache
+3. Added `cj/clear-oauth2-auto-cache` helper function in auth-config.el
+4. Documented fix in auth-config.el commentary (lines 16-22)
+
+**Result:**
+- GPG passphrase prompted ONCE per Emacs session (when first accessing tokens)
+- oauth2-auto now caches tokens in memory (oauth2-auto--plstore-cache)
+- No more interruptions during org-gcal auto-sync every 30 minutes
+- Workflow is now frictionless as intended
+
+**Testing:**
+After restart:
+1. First org-gcal sync prompts for passphrase (expected)
+2. Subsequent syncs use cached tokens (no prompts)
+3. Cache persists until Emacs closes
+
+**Files Modified:**
+- elpa/oauth2-auto-20250624.1919/oauth2-auto.el (cache fix)
+- modules/auth-config.el (documentation + helper function)
+
+Priority [#A] because password prompts every 15 minutes violated "Frictionless" value.
+Fixed 2025-11-11.
+
+** DONE [#A] Fix audio recording device selection - still broken with Jabra headset
+CLOSED: [2025-11-11 Mon]
+
+✅ **Fixed audio recording bug + improved UX**
+
+**Root Cause:**
+Auto-detection only looked for `analog.*stereo` which matched laptop audio but never
+Bluetooth/Jabra devices. User was always recording from laptop mic (silent when using Jabra).
+
+**What Was Fixed:**
+
+1. **Removed broken auto-detection** (lines 58-77)
+ - Old code only detected built-in laptop audio
+ - Never detected Bluetooth/USB/Jabra devices
+ - This is why recordings were silent
+
+2. **Force explicit device selection on first use**
+ - C-; r a now prompts for device setup if not configured
+ - Suggests quick setup (C-; r c) by default
+ - Device selection persists across Emacs sessions
+
+3. **Simplified keybindings to toggle start/stop**
+ - C-; r a → Toggle audio recording (start/stop)
+ - C-; r v → Toggle video recording (start/stop)
+ - Removed separate stop keybindings (A, V)
+ - One key to remember, press again to stop!
+
+4. **Added device testing functions** (lines 233-314)
+ - C-; r t b → Test both mic + monitor (guided, RECOMMENDED)
+ - C-; r t m → Test microphone only (5 sec)
+ - C-; r t s → Test system audio/monitor only (5 sec)
+ - Catch hardware issues before important recordings
+
+5. **Added modeline recording indicator**
+ - 🔴Audio appears when recording audio
+ - 🔴Video appears when recording video
+ - 🔴A+V appears when recording both
+ - Indicator and toggle always in sync (same process variables)
+ - Process sentinel auto-clears on crash/kill
+
+**New Workflow:**
+```
+Press C-; r a
+ ↓
+First time? → Device setup → Choose Jabra → Start (🔴Audio appears)
+ ↓
+Already configured? → Start immediately (🔴Audio appears)
+ ↓
+Press C-; r a again → Stop (🔴 disappears)
+```
+
+**Files Modified:**
+- modules/video-audio-recording.el (removed auto-detect, added tests, toggle functions, modeline indicator)
+- modules/modeline-config.el (added 🔴 recording indicator to right side)
+
+**Testing:**
+After Emacs restart:
+1. Press C-; r a
+2. Choose "Bluetooth Headset" (Jabra)
+3. See 🔴Audio in modeline
+4. Speak and play audio
+5. Press C-; r a to stop
+6. Verify recording has audio
+
+Priority [#A] because blocked daily recording and transcription workflows.
+Fixed 2025-11-11.
+
+** DONE [#A] Remove network check from startup (saves 1+ seconds)
+CLOSED: [2025-10-31 Fri]
+
+✅ Deleted blocking ping check. Startup improved from 6.2s to 5.4s.
+Now uses package priorities: .localrepo (200) > online repos (25).
+
+** DONE [#A] Fix cj/goto-git-gutter-diff-hunks (missing function causing errors)
+CLOSED: [2025-11-03 Sun]
+
+✅ Implemented missing function in modules/vc-config.el
+- Added `cj/goto-git-gutter-diff-hunks` function (lines 118-124)
+- Uses consult-line to search for diff markers (^[+\-])
+- Enables interactive jumping to any changed line via C-; v d
+- Function properly documented with docstring
+- No linting issues, compiles cleanly
+
+Quick win completed - 5 minutes actual time.
+
+** DONE [#A] Fix chime-check throw with no catch block
+CLOSED: [2025-11-01 Fri]
+
+Error: "(no-catch --cl-block-chime-check-- nil)"
+Chime was throwing to a catch block that doesn't exist.
+Location: chime package - chime-check() function at line 1540
+Fix: Changed defun to cl-defun to provide implicit catch block for cl-return-from.
+
+Fixed in ~/code/chime.el/chime.el:1540
+
+Added regression test: test-integration-startup-early-return-on-validation-failure
+Created Makefile with test targets (unit, integration, all, by-file, by-name)
+Updated README.org with Development/Testing section
+
+All integration tests pass (5/5) ✅
+
+** DONE [#A] Implement cj/diff-buffer-with-file (compare buffer with saved version)
+CLOSED: [2025-10-31 Fri]
+
+Bound to C-; b D. Weekly need satisfied.
+
+** DONE [#A] Add comprehensive test coverage for video-audio-recording module
+CLOSED: [2025-11-03 Sun]
+
+✅ Created comprehensive test suite following quality-engineer.org standards:
+- 9 test files (8 unit + 1 integration)
+- 83 test cases with 100% pass rate
+- Test categories: Normal, Boundary, Error cases
+- 6 test fixtures for reproducible testing
+- Mocking strategy using cl-letf
+- Integration test validates complete parse→group→friendly-names workflow
+- Tests document bugs in legacy detect functions
+- Critical validation: Bluetooth MAC normalization across component boundaries
+
+✅ Refactored code for testability:
+- Extracted `cj/recording--parse-pactl-output` internal parser
+- Separated I/O from business logic
+
+✅ Fixed all linting warnings (checkdoc):
+- 6 spacing/grammar issues resolved
+- `make lint` now passes cleanly
+
+✅ All changes committed and pushed to all remotes (origin + github)
+
+Commits:
+- 0a69c58: test: Add comprehensive test suite for video-audio-recording module
+- b086539: style: Fix checkdoc warnings in video-audio-recording.el
+
+*** DONE [#C] Add device testing command cj/recording-test-devices
+CLOSED: [2026-02-06 Thu]
+Records 3 seconds of audio.
+Plays it back.
+Confirms devices work before real recording.
+
+*** CANCELLED [#C] Add recording status display (optional via flag, default off)
+CLOSED: [2026-02-14 Sat]
+Emoji modeline icon is sufficient.
+
+*** CANCELLED [#C] Add recording presets
+CLOSED: [2026-02-14 Sat]
+Only used for meetings; emoji icon is good-enough reminder. Gold-plating.
+
+*** CANCELLED [#C] Build recording history buffer
+CLOSED: [2026-02-14 Sat]
+Opening recordings in dirvish is sufficient.
+
+*** TODO [#C] Add post-processing hooks
+Auto-compress after recording.
+Move to cloud sync directory.
+Generate transcript (once transcription workflow exists).
+
+** DONE [#A] Delay in modeline lines and columns update
+CLOSED: [2025-11-08 Fri]
+
+✅ Fixed modeline position lag by replacing expensive function calls with cached values.
+
+**Problem:**
+- Line/column numbers lagged behind cursor movement
+- Used `line-number-at-pos` which counts from buffer start on every update
+- Performance degraded in large files
+
+**Solution:**
+- Replaced with built-in format specifiers `%l` and `%c` (modeline-config.el:81)
+- These use cached values maintained by line-number-mode and column-number-mode
+- Explicitly enabled line-number-mode in ui-config.el:53
+- Zero performance overhead - cached values update instantly
+
+**Result:**
+- Modeline position now updates instantly with cursor movement
+- No lag, even in large files
+- Maintains same "L:line C:col" format
+
+** DONE [#B] Toggle org-appear on/off
+CLOSED: [2025-11-16 Sat]
+
+✅ **Implemented toggle function with C-c C-a keybinding**
+
+Created `cj/org-appear-toggle` function that toggles org-appear-mode on/off in
+current org buffer. Default is OFF (cleaner for reading), can be toggled ON when
+editing links, then toggled OFF again.
+
+**Implementation:**
+- Removed :disabled flag and :hook (default: OFF)
+- Created cj/org-appear-toggle function with clear user feedback
+- Bound to C-c C-a in org-mode-map (unbound, no conflicts)
+- Tested: toggles correctly, all tests pass
+
+**Usage:**
+- C-c C-a: Toggle on/off
+- Default: OFF (links and emphasis markers stay hidden)
+- Messages show current state clearly
+
+Moved from inbox 2025-11-07. Completed 2025-11-16.
+
+** DONE [#B] Consider implementing cron download of Google Calendar to replace org-gcal
+CLOSED: [2025-11-16 Sat]
+
+Replaced problematic org-gcal OAuth workflow with calendar-sync.el module.
+Implemented pure Elisp .ics parser with timer-based sync (no cron needed).
+
+**Current Problem:**
+From TODO at line 22-66:
+- org-gcal prompts for password every ~15 minutes
+- OAuth token refresh bypasses cache
+- plstore symmetric encryption cache issues
+- Interrupts workflow constantly
+- Makes calendar sync painful instead of seamless
+
+**Proposed Solution:**
+Instead of OAuth-based sync (org-gcal), use Google Calendar's public iCalendar URLs:
+1. Download .ics file via cron (every 15-30 minutes)
+2. Parse .ics file into org-mode format
+3. Update org-agenda files automatically
+4. No OAuth, no passwords, no interruptions
+
+**Benefits:**
+- ✓ No password prompts (public calendar URL or one-time API key)
+- ✓ No OAuth token refresh issues
+- ✓ Runs in background (cron), never interrupts work
+- ✓ Simpler architecture (download → parse → update)
+- ✓ Can work offline (reads last downloaded .ics)
+- ✓ More reliable (fewer moving parts)
+- ✓ No plstore symmetric encryption issues
+
+**Drawbacks:**
+- ✗ Read-only (can't create/update events from Emacs)
+- ✗ Need to manually get calendar iCal URL
+- ✗ Requires cron setup (one-time configuration)
+- ✗ May have sync delay (up to cron interval)
+
+**Investigation:**
+
+1. **Get Google Calendar iCal URL:**
+ - Open Google Calendar settings
+ - Find "Integrate calendar" section
+ - Copy secret iCal address (https://calendar.google.com/calendar/ical/...)
+ - Store in auth-source (encrypted)
+
+2. **Test iCal download:**
+ ```bash
+ curl -o calendar.ics "https://calendar.google.com/calendar/ical/.../basic.ics"
+ ```
+ - Verify it downloads
+ - Check .ics format
+ - Confirm events are present
+
+3. **Research iCal parsing:**
+ - Does Emacs have built-in iCal parser? (icalendar.el)
+ - Check icalendar-import-file function
+ - Test parsing downloaded .ics file
+ - Verify it creates org entries
+
+4. **Design cron workflow:**
+ ```bash
+ # Every 15 minutes
+ */15 * * * * curl -s "$(cat ~/.calendar-url)" -o ~/calendars/gcal.ics
+ ```
+ - Downloads silently in background
+ - Emacs watches file for changes (file-notify)
+ - Auto-reimport when changed
+
+**Possible Implementations:**
+
+A. **Full replacement (recommended):**
+ - Remove org-gcal entirely
+ - Use cron + icalendar.el
+ - Read-only calendar view in org-agenda
+ - Create events directly in Google Calendar web UI
+
+B. **Hybrid approach:**
+ - Keep org-gcal for writing events
+ - Use cron download for reading events
+ - Disable org-gcal auto-sync (no password prompts)
+ - Manually trigger org-gcal only when creating events
+
+C. **Enhanced cron:**
+ - Cron downloads .ics
+ - Emacs function parses and updates org files
+ - Add file-notify watcher for auto-update
+ - Optional: Convert two-way with CalDAV later
+
+**Implementation Sketch:**
+```elisp
+(defun cj/calendar-import-gcal ()
+ "Import Google Calendar from downloaded .ics file."
+ (interactive)
+ (let ((ics-file "~/calendars/gcal.ics")
+ (org-file "~/org/calendar.org"))
+ (when (file-exists-p ics-file)
+ (icalendar-import-file ics-file org-file)
+ (message "Imported calendar from %s" ics-file))))
+
+;; Auto-import when .ics file changes
+(file-notify-add-watch
+ "~/calendars/gcal.ics"
+ '(change)
+ (lambda (event) (cj/calendar-import-gcal)))
+```
+
+**Related Files:**
+- modules/org-gcal-config.el (current problematic implementation)
+- Emacs built-in: icalendar.el (iCal parsing)
+- System: crontab -e (download schedule)
+- ~/.authinfo.gpg (store calendar URL securely)
+
+**Related Docs:**
+- Current problem: TODO line 22-66 (password prompts every 15 min)
+- icalendar.el manual: C-h f icalendar-import-file
+- Google Calendar iCal format documentation
+- V2MOM Method 1: Frictionless (no interruptions!)
+
+**Success Criteria:**
+- Calendar events appear in org-agenda
+- No password prompts during work
+- Updates automatically in background (cron)
+- Can work offline with last sync
+- Setup is one-time configuration
+- Simpler than current org-gcal setup
+
+**Testing Plan:**
+1. Get iCal URL from Google Calendar
+2. Test download: `curl URL -o test.ics`
+3. Test import: `M-x icalendar-import-file`
+4. Verify org entries created correctly
+5. Set up cron job
+6. Wait for auto-update
+7. Confirm events in org-agenda
+8. Disable org-gcal auto-sync
+9. Monitor for 1 week (no password prompts?)
+
+**Decision Point:**
+This is a significant architectural change. Need to:
+1. Test proof-of-concept first (manual download + import)
+2. Evaluate if read-only is acceptable
+3. Compare to fixing OAuth password prompts
+4. Consider hybrid approach if two-way sync needed
+
+**Note:**
+Priority [#B] because this could eliminate the #1 daily irritant (password prompts
+every 15 minutes). If proof-of-concept works, this is higher value than fixing
+OAuth issues. Simpler architecture = fewer problems.
+
+** DONE [#B] Add time-zones package for quick timezone lookups
+CLOSED: [2025-11-14 Fri 02:42]
+
+IRRITANT: Need to frequently check time differences between cities (London, Lisbon,
+New Orleans, San Francisco) for meetings and coordination. Currently requires stopping
+work, searching web/using external app, context switching back.
+
+**Pain Point:**
+Multiple times per week, need to know "what time is it in London right now?" or
+"if I schedule this for 2pm my time, what time is that in Lisbon?" This breaks
+flow and requires leaving Emacs.
+
+**Solution:**
+Use time-zones package: https://github.com/xenodium/time-zones
+
+Built-in world-clock exists (M-x world-clock) but lacks two critical features:
+1. Can't interactively add cities with fuzzy search
+2. Can't shift time forward/backward to check future times
+
+time-zones package adds both features - making timezone checks instant and frictionless.
+
+**Expected Workflow:**
+- M-x time-zones (or keybinding C-; T z or similar)
+- Interactively add/remove cities with completion
+- Shift time forward/backward to check meeting times
+- Stay in Emacs, maintain flow
+
+**Files:**
+- Create new module: modules/time-zones-config.el
+- Add require to init.el in appropriate section
+- Configure default cities list (London, Lisbon, New Orleans, San Francisco)
+- Add keybinding (suggest C-; T z for time zones)
+
+**V2MOM Alignment:**
+Method 1 - Frictionless: Eliminates context switch for common timezone queries.
+Intuitive value: Quick keybinding for frequent operation.
+
+** DONE [#B] Fix go-ts-mode-map keybinding error (void-variable)
+CLOSED: [2025-11-03 Sun]
+
+Error: "Debugger entered--Lisp error: (void-variable go-ts-mode-map)"
+Location: modules/prog-go.el - trying to bind keys before mode loads.
+
+✅ Already fixed in commit 196b289 (Nov 2, 2025)
+- Moved keybinding from `:bind (:map go-ts-mode-map ...)` to hook function
+- Keybinding now set in `cj/go-mode-keybindings` called via `:hook`
+- Function executes after mode loads, ensuring keymap exists
+- Today's cleanup: Removed unused forward declarations (lines 34-35)
+
+Fix was: Wrap keybinding in hook function instead of :bind clause.
+Result: No more void-variable error, keybinding works correctly.
+
+** DONE [#B] Fix video/audio recording module (use constantly, just broke)
+CLOSED: [2025-11-03 Sun]
+
+Main issue: No way to select audio devices when multiple are available.
+Plugging in external audio interface broke recording - only captured input, not output.
+
+✅ COMPLETED - Module now has robust device detection and selection.
+
+*** DONE [#A] Add diagnostic command cj/recording-list-devices
+CLOSED: [2025-11-03 Sun]
+
+✅ Created `cj/recording-list-devices` command (C-; r d)
+Shows ALL available PulseAudio/PipeWire sources with drivers and states.
+Displays current configuration.
+Helps debug why auto-detection fails.
+
+*** DONE [#A] Add device selection UI
+CLOSED: [2025-11-03 Sun]
+
+✅ Created TWO selection workflows:
+1. `cj/recording-select-devices` (C-; r s) - Full manual control
+ - Select mic and system audio separately
+ - Interactive completion with device states
+2. `cj/recording-quick-setup-for-calls` (C-; r c) - Quick call setup
+ - Smart device pairing (groups mic + monitor by hardware)
+ - One selection for both mic and system audio
+ - Handles Bluetooth MAC normalization
+
+Devices cached in variables for future recordings.
+Can switch devices without restarting Emacs.
+
+*** DONE [#B] Improve error messages
+CLOSED: [2025-11-03 Sun]
+
+✅ Error messages now include:
+- Guidance to run `cj/recording-select-devices`
+- Clear indication when auto-detection fails
+- User-friendly prompts for manual selection
+
+*** DONE [#B] Make device detection more flexible
+CLOSED: [2025-11-03 Sun]
+
+✅ Implemented multi-level fallback system:
+1. Auto-detect using pactl output parsing
+2. Prompt user to select manually if auto-detect fails
+3. Error with helpful guidance if user declines
+
+✅ Smart device grouping in `cj/recording-group-devices-by-hardware`:
+- Handles USB, PCI (built-in), and Bluetooth devices
+- Normalizes Bluetooth MAC addresses (colons ↔ underscores)
+- Assigns friendly names (e.g., "Built-in Laptop Audio", "Bluetooth Headset")
+- Filters incomplete devices (must have both mic and monitor)
+
+✅ Supports both PulseAudio and PipeWire (both use pactl).
+
+*** TODO [#B] Validate recording startup
+Check process status after starting.
+Parse ffmpeg output for errors.
+Show actual ffmpeg command for debugging.
+
+** DONE [#C] Fix grammar checker performance (currently disabled)
+CLOSED: [2025-11-04 Mon]
+
+✅ **Installed and configured LanguageTool for comprehensive grammar checking**
+
+Replaced disabled grammar checker with on-demand LanguageTool integration:
+- Installed LanguageTool 6.6-2 from Arch repos (222MB)
+- Created wrapper script: scripts/languagetool-flycheck (Python 3)
+- Integrated with flycheck for on-demand checking via C-; ?
+- Removed proselint (redundant - LanguageTool catches more)
+- No performance impact: only runs when explicitly invoked
+- Installation instructions added to modules/flycheck-config.el commentary
+
+LanguageTool catches:
+- Real grammar errors (subject-verb agreement, tense, etc.)
+- Missing punctuation (commas, periods)
+- Common mistakes (could of → could have)
+- Style issues (redundant phrases, wordiness)
+
+Workflow: Open org/text/markdown file → press C-; ? → see errors in *Flycheck errors* buffer
+
+** DONE [#C] cj/flyspell-then-abbrev loses keybinding in scratch org-mode buffer
+CLOSED: [2025-11-08 Fri]
+
+✅ Fixed keybinding issue in org-mode buffers.
+
+**Problem:**
+1. Autoload cookies were just comments and never executed
+2. Org-mode was overriding C-' with org-cycle-agenda-files
+
+**Solution:**
+- Set keybindings directly when module loads (lines 239-240)
+- Explicitly override org-mode's C-' after org loads (lines 244-245)
+- Both C-' and C-c f now work correctly in all buffers including org-mode
+
+File modified: modules/flyspell-and-abbrev.el:235-251
+
+* Method 2: Stop Problems Before They Appear [4/8]
+** TODO [#B] Write Complete ERT Tests for This Config [0/31]
+Unit and Integration Tests should be added as subtasks below, marked done when complete.
+
+*High-value test targets (no coverage, testable logic, daily use):*
+
+*** TODO custom-case — pure case conversion functions (upper/lower/title)
+*** TODO custom-datetime — date/timestamp insertion and formatting
+*** TODO host-environment — platform detection (env-macos-p, env-wayland-p, etc.)
+*** TODO hugo-config — draft toggle, slug generation, post template
+*** TODO org-capture-config — template building (relates to capture perf optimization)
+*** TODO modeline-config — custom segment construction
+*** TODO external-open — file-type detection and external app dispatch
+*** TODO reconcile-open-repos — dirty repo scanning logic
+*** TODO media-utils — URL download/play logic
+*** TODO org-config — org-mode utility functions
+*** TODO org-export-config — export helper functions
+*** TODO local-repository — package snapshot logic
+*** TODO show-kill-ring — kill ring display logic
+*** TODO system-commands — reboot/logout/system action functions
+*** TODO config-utilities — debug helper functions
+
+*Modules with partial coverage (expand existing tests):*
+
+*** TODO org-agenda-config — caching/TTL logic untested (only build-list covered)
+*** TODO org-contacts-config — expand beyond capture/parse
+*** TODO prog-shell — expand beyond make-script-executable
+*** TODO ui-config — expand beyond buffer-status/cursor-color
+*** TODO org-refile-config — expand beyond build-targets
+*** TODO org-webclipper — expand beyond process (only 1 test file)
+*** TODO org-noter-config — expand beyond generate-notes/title-to-slug
+*** TODO browser-config — expand beyond current single test file
+*** TODO flycheck-config — expand beyond languagetool setup
+*** TODO org-drill-config — expand beyond first-function/font-switching
+
+*Lower priority (testable but less critical):*
+
+*** TODO chrono-tools — timer/clock functions
+*** TODO help-utils — search dispatch (arch-wiki, devdoc, tldr, wikipedia)
+*** TODO dirvish-config — wallpaper setter, custom functions
+*** TODO dwim-shell-config — shell command definitions
+*** TODO elfeed-config — podcast/feed helper functions
+*** TODO eww-config — browser helper functions
+
+** TODO [#B] Review all config and pull library functions into system-lib file
+
+Extract reusable utility functions scattered across modules into system-lib.el
+for better code organization and reusability.
+
+**Goal:**
+Create a centralized system utilities library where generic functions that check
+system state, detect programs, or provide low-level system operations can live.
+This makes them:
+- Easily discoverable
+- Reusable across modules
+- Testable in isolation
+- Following single-responsibility principle
+
+**Current State:**
+- system-lib.el exists with `cj/executable-exists-p` function
+- Already required at top of init.el (System Configuration section)
+- Has comprehensive test coverage (test-system-lib-executable-exists-p.el)
+
+**Task:**
+1. Search entire config for candidate functions:
+ - System queries (program detection, path checking, environment vars)
+ - File system utilities (beyond buffer-file operations)
+ - Process utilities
+ - Platform detection helpers
+2. Review each module for extraction candidates:
+ - host-environment.el (already has some, may have more)
+ - system-utils.el (may contain generic utilities)
+ - Any module with functions that don't depend on mode-specific context
+3. Move appropriate functions to system-lib.el:
+ - Update function documentation
+ - Add require statements where functions are used
+ - Maintain backward compatibility (old locations can call new ones)
+4. Add comprehensive test coverage for all moved functions
+5. Document the purpose/scope of system-lib.el in its Commentary section
+
+**Criteria for inclusion in system-lib.el:**
+- ✓ Pure utility functions (no side effects)
+- ✓ System-level queries (executable detection, path operations)
+- ✓ Platform-agnostic where possible
+- ✓ No dependencies on mode-specific functionality
+- ✗ NOT buffer/file operations (those stay in custom-buffer-file.el)
+- ✗ NOT user-facing commands (those stay in their domain modules)
+
+**Related Files:**
+- modules/system-lib.el (target file)
+- modules/host-environment.el (likely source)
+- modules/system-utils.el (likely source)
+- modules/config-utilities.el (check for candidates)
+- tests/test-system-lib-*.el (add tests for moved functions)
+
+**Related Docs:**
+- Recent refactoring: Created system-lib.el with cj/executable-exists-p
+- Testing guidance: ai-prompts/quality-engineer.org
+- V2MOM Method 2: Stop Problems Before They Appear (better organization)
+
+**Success Criteria:**
+- All generic system utilities consolidated in system-lib.el
+- Each function has comprehensive test coverage
+- No functionality broken (all tests pass)
+- Documentation explains purpose and scope of system-lib.el
+- Other modules properly require system-lib where needed
+
+** TODO [#C] Migrate from Company to Corfu
+:PROPERTIES:
+:COMPLETE_CONFIG: [[file:docs/someday-maybe.org::1611][todo.org:1611-1639]]
+:END:
+
+Complete config already exists in someday-maybe.org. Just needs to be executed.
+
+** TODO [#C] Integrate prescient with Corfu (smart sorting)
+
+Already using prescient with vertico. Extend to Corfu after migration.
+
+** DONE [#B] Move cj/log-silently to system-lib
+CLOSED: [2025-11-16 Sun 18:36]
+
+The `cj/log-silently` function is a generic utility for logging messages without
+displaying them in the echo area. It should be moved to system-lib.el for better
+organization and reusability across modules.
+
+**Current Problem:**
+- cj/log-silently is likely defined in a specific module
+- It's a generic logging utility that could be used by any module
+- Not easily discoverable for reuse
+- Doesn't follow the system-lib pattern we're establishing
+
+**What is cj/log-silently?**
+This function logs messages to the *Messages* buffer without interrupting the user
+by displaying them in the echo area (minibuffer). Useful for debugging and tracing
+code execution without breaking user flow.
+
+**Task:**
+1. **Find current location:**
+ ```bash
+ grep -rn "defun cj/log-silently" modules/
+ ```
+
+2. **Review implementation:**
+ - Check if it has dependencies on mode-specific functionality
+ - Verify it's truly generic (should be)
+ - Check for any callers that need updating
+
+3. **Move to system-lib.el:**
+ - Cut from current location
+ - Paste into system-lib.el
+ - Add appropriate commentary/docstring
+ - Ensure proper section organization
+
+4. **Update callers:**
+ - Find all uses: `grep -rn "cj/log-silently" modules/`
+ - Add `(require 'system-lib)` to any module that uses it
+ - Verify no circular dependencies
+
+5. **Write tests:**
+ Create `tests/test-system-lib-log-silently.el` with coverage for:
+ - Normal cases: logging simple messages
+ - Boundary cases: empty strings, very long messages, special characters
+ - Error cases: nil input, non-string input
+ - Verify output: check *Messages* buffer contains logged text
+ - Verify silence: ensure nothing appears in echo area
+
+**Expected Signature:**
+```elisp
+(defun cj/log-silently (format-string &rest args)
+ "Log a message to *Messages* buffer without displaying in echo area.
+FORMAT-STRING and ARGS work like `message' but output is not shown to user."
+ (let ((inhibit-message t))
+ (apply #'message format-string args)))
+```
+
+**Related Files:**
+- modules/system-lib.el (destination)
+- Current module where cj/log-silently lives (TBD - find it)
+- All modules that call cj/log-silently (update requires)
+- tests/test-system-lib-log-silently.el (NEW - create this)
+
+**Related Docs:**
+- System-lib refactoring initiative (previous TODO)
+- quality-engineer.org (testing guidance)
+- Recent refactoring: moved cj/executable-exists-p to system-lib
+- V2MOM Method 2: Stop Problems Before They Appear (better organization)
+
+**Success Criteria:**
+- cj/log-silently moved to system-lib.el
+- All callers updated with proper requires
+- Comprehensive test coverage (normal/boundary/error cases)
+- All existing tests still pass (no regressions)
+- Function works identically to before
+- Well-documented in system-lib.el
+
+**Testing:**
+1. Run all tests before move (baseline)
+2. Move function and update requires
+3. Run all tests after move (verify no breakage)
+4. Run new cj/log-silently tests (verify behavior)
+5. Test in real usage (logging works, messages not shown)
+
+**Note:**
+Priority [#B] because this is part of the larger system-lib consolidation effort
+(separate TODO). Logging utilities are commonly used, so centralizing them improves
+discoverability and encourages consistent logging patterns across the codebase.
+
+** DONE [#C] Switch to mood-line (actually: built custom modeline)
+CLOSED: [2025-11-03 Sun]
+
+✅ **Built custom modeline (better than mood-line)**
+
+Went beyond mood-line and created a fully custom modeline using only built-in
+Emacs functionality to avoid native-compilation issues. Features:
+
+**Architecture:**
+- Named segment system using defvar-local (easy to reorder)
+- Emacs 30 built-in right-alignment (mode-line-format-right-align)
+- All segments marked as risky-local-variable for proper evaluation
+
+**Interactive Features:**
+- Color-coded buffer names (green=writeable, red=read-only, gold=overwrite)
+- VC branch with git symbol () and state-based coloring
+- Mouse click handlers: buffer name (prev/next), branch (vc-diff), mode (describe-mode)
+- Help-echo tooltips on all segments
+- String truncation for narrow windows (< 100 chars wide)
+- Active-window-only display for branch and misc-info (less clutter)
+
+**Layout:**
+- Left: Major mode, buffer name, position (L:# C:#)
+- Right: Git branch, chime notifications
+
+**Bug Fixes:**
+- Disabled async native compilation (prevented "Selecting deleted buffer" errors)
+- Fixed difftastic loading (:demand → :defer)
+- Abstracted buffer status colors to user-constants.el
+
+Inspired by Prot's modeline design. See commit c0c4b17.
+
+** DONE [#C] Remove deprecated tree-sitter package (rely on treesit-auto)
+CLOSED: [2025-11-03 Sun]
+
+✅ Removed deprecated tree-sitter package from modules/prog-general.el
+- Deleted `(use-package tree-sitter)` on line 97
+- Now relies solely on Emacs 29+ built-in treesit with treesit-auto
+- treesit-auto continues to manage tree-sitter grammars automatically
+- No functionality lost, cleaner dependency tree
+
+** DONE [#C] Add org-appear (show emphasis markers only when point is on them)
+CLOSED: [2025-11-03 Sun]
+
+✅ Added org-appear package to modules/org-config.el
+- Shows emphasis markers (* / _) only when cursor is on them
+- Also shows link markup and sub/superscripts when editing
+- Changed org-fontify-emphasized-text from nil to t (line 75)
+- Updated comment on line 71 to reference org-appear
+- Cleaner editing experience while maintaining visual clarity
+
+* Method 3: Make *Fixing* Emacs Frictionless [0/9]
+** DONE [#A] Write tests for cj/make-script-executable (suspected broken)
+CLOSED: [2025-11-11 Tue]
+
+The `cj/make-script-executable` function automatically makes shell scripts executable
+when they have a shebang, but has no test coverage. **Suspected to be broken/not working.**
+This is a critical function that modifies file permissions and runs on every save.
+
+**Function Location:**
+modules/prog-shell.el:158-167
+
+**Why This Matters:**
+1. Runs automatically on after-save-hook in shell-script-mode (high frequency)
+2. Modifies file permissions (security-relevant)
+3. If broken, scripts won't become executable automatically
+4. No test coverage means bugs go undetected
+
+**Investigation First:**
+1. Test manually: Create test.sh with `#!/bin/bash`, save, check if executable
+2. Check if function is actually hooked to after-save-hook
+3. Verify conditions in function logic are correct
+4. Look for any error messages in *Messages* buffer
+
+**Then Write Tests:**
+Following quality-engineer.org patterns:
+- Normal cases: Various shebangs (bash, python, ruby, etc.)
+- Boundary cases: Shebang with spaces, not at start, already executable
+- Error cases: No file, read-only filesystem, permission errors
+
+**Estimated Work:**
+- Manual testing: 15 minutes
+- Writing comprehensive tests: 2-3 hours
+- ~20-25 tests total
+
+**Success Criteria:**
+- Confirm function works or identify bug
+- Comprehensive test coverage
+- Tests document expected behavior
+- Can refactor safely with tests as safety net
+
+Priority [#B] because if broken, it's a daily workflow issue (scripts don't auto-execute).
+Moved from inbox 2025-11-11.
+
+** DONE [#A] Fix difftastic integration - not showing semantic diffs (just unified diff)
+CLOSED: [2025-11-11 Tue]
+
+Difftastic was marked as "integrated" but diffs in magit and custom-buffer-file.el look
+identical to standard unified diffs. **Likely not actually using difftastic** - probably
+falling back to git diff or missing a configuration switch.
+
+**Problem:**
+Two places where difftastic should work but doesn't:
+1. **Magit diffs** - Should show semantic diffs with D/S keybindings, but looks like unified diff
+2. **Buffer diff** (custom-buffer-file.el) - cj/diff-buffer-with-file should use difftastic but looks like unified diff
+
+**Investigation:**
+1. Check if difftastic binary actually gets called:
+ - Test: `difft --version` (verify binary exists)
+ - Test: `difft file1.el file2.el` manually to see what output looks like
+ - Should show syntax-aware, tree-based diff (very different from unified)
+
+2. Review vc-config.el difftastic setup (lines ~176-190):
+ - Is difftastic.el package loaded? (check with `M-x package-list-packages`)
+ - Are keybindings actually bound? (check magit-diff-mode-map)
+ - Is there a configuration switch we're missing?
+
+3. Check custom-buffer-file.el:
+ - Claims to use ediff (line 554-565), not difftastic
+ - Confusion: Is it supposed to use difftastic or ediff?
+ - If ediff, that's different tool (interactive split-screen, not semantic)
+
+**Possible Issues:**
+A. difftastic.el not actually loaded (:defer preventing it)
+B. Missing transient menu configuration for magit
+C. Need to enable difftastic-mode explicitly
+D. Keybindings shadowed by other bindings
+E. ANSI color codes not rendering (looks wrong but is difftastic)
+
+**Expected Behavior:**
+Difftastic output should look VERY different from unified diff:
+- Tree-based syntax matching
+- Side-by-side or structured format
+- Language-aware (knows it's elisp/org/etc)
+- Shows matched nodes, not just line changes
+
+**Next Steps:**
+1. Run difft manually on two .el files to see expected output
+2. Try calling difftastic functions directly: `M-x difftastic-magit-diff`
+3. Check *Messages* for errors when using D/S in magit
+4. Review difftastic.el documentation for required configuration
+
+**Related Files:**
+- modules/vc-config.el (difftastic config)
+- modules/custom-buffer-file.el (buffer diff - might be ediff, not difftastic?)
+- Binary: /usr/bin/difft
+
+**Success Criteria:**
+- Diffs in magit show obvious semantic/structural differences
+- Output clearly different from unified diff
+- Can visually identify it's difftastic (not git diff)
+- Documented how to use and what to expect
+
+Priority [#B] because if not working, we're not getting the benefit of difftastic integration.
+Moved from inbox 2025-11-11.
+
+** TODO [#B] Build debug-profiling.el module
+
+Reusable profiling infrastructure for any future performance work.
+** TODO [#C] Evaluate Buttercup for integration tests
+** TODO [#B] Add project-aware ERT test isolation when switching projects
+
+When switching between elisp projects (e.g., emacs.d to chime.el), previously loaded
+ERT tests remain in memory causing confusion and wrong tests to run.
+
+**Problem:**
+- ERT tests globally registered in Emacs session
+- `M-x ert RET t RET` runs ALL loaded tests from ALL projects
+- Can accidentally run emacs.d tests when working on chime.el
+- Current workaround: restart Emacs (loses session state)
+
+**Solution:**
+Create `cj/ert-clear-tests` and `cj/ert-run-current-project-tests`:
+- Clear tests when switching projects (hook into project-switch)
+- Use test name prefixes to selectively clear (cj/ vs chime-)
+- Only run current project's tests
+
+**Success Criteria:**
+- Switch projects → old tests cleared
+- Only current project's tests run with `M-x ert`
+- Works with both interactive and batch runs
+
+Priority [#B] because affects daily workflow when working on multiple elisp projects.
+Moved from inbox 2025-11-11.
+
+** DONE [#B] Remove ANSI color codes from Makefile - breaks test output readability
+CLOSED: [2025-11-11 Tue]
+
+ANSI color codes render incorrectly in some terminals, making test output unreadable.
+Can see it's colored red, but can't read what the actual error message says due to
+escape code littering throughout the text. Blocks debugging.
+
+**Problem:**
+- Makefile uses variables like `COLOR_GREEN`, `COLOR_RED`, `COLOR_BLUE`
+- These insert ANSI escape codes like `\033[0;32m` into output
+- Makes output harder to read, especially in logs or when piped
+- Color codes don't work well in all terminals
+- Unnecessary complexity
+
+**Proposed Solution:**
+Replace color codes with simple text markers:
+- `✓` (checkmark) for success - KEEP THIS
+- `✗` (x mark) for failure - KEEP THIS
+- `[i]` for informational messages
+- Remove color entirely, rely on symbols alone
+
+**Examples:**
+Current:
+```
+\033[0;32m✓ All unit tests passed\033[0m
+\033[0;31m✗ 18 unit test file(s) failed\033[0m
+\033[0;34mRunning unit tests...\033[0m
+```
+
+Proposed:
+```
+✓ All unit tests passed
+✗ 18 unit test file(s) failed
+[i] Running unit tests...
+```
+
+**Implementation:**
+1. Find all `COLOR_*` variables in Makefile
+2. Replace colored text with plain text + symbols
+3. Remove color variable definitions
+4. Test that output is still clear and readable
+
+**Related Files:**
+- Makefile (all COLOR_ variables and usage)
+
+**Success Criteria:**
+- No ANSI escape codes in Makefile
+- Output still clear and readable
+- Uses text symbols (✓, ✗, [i]) appropriately
+- Simpler, cleaner Makefile
+- Test output works in any terminal/CI environment
+
+**Note:**
+Priority [#B] because it improves readability and maintainability. Not urgent,
+but makes the codebase cleaner and more portable.
+
+** TODO [#C] Build localrepo out (package snapshot system)
+
+Repeatable installs and safe rollbacks.
+
+*** TODO [#C] Document localrepo limitations (treesitter grammars not included)
+
+.localrepo only contains packages from package.el archives.
+Treesitter grammars are downloaded separately by treesit-auto on first use.
+For true offline reproducibility, need to cache treesitter grammars separately.
+
+** TODO [#C] Integrate Buttercup (behavior-driven integration tests)
+
+Complex workflow testing capability.
+
+** TODO [#D] Optimize lorem-optimum performance for faster text generation
+
+Lorem-optimum text generation is generally slow but doesn't completely break workflow.
+Two benchmark tests were disabled (marked :slow) because they take MINUTES instead of seconds.
+
+**Current State:**
+- Tests disabled to unblock test suite (DONE 2025-11-09)
+- Performance is acceptable for daily use, but could be better
+- liber-primus.txt may be too large for optimal performance
+
+**Investigation:**
+1. Profile lorem-optimum to find bottlenecks
+2. Check if liber-primus.txt size needs optimization
+3. Optimize performance to get tests under 5 seconds
+4. Re-enable benchmark tests once performance is acceptable
+
+**Related Files:**
+- modules/lorem-optimum.el (needs profiling and optimization)
+- tests/test-lorem-optimum-benchmark.el (tests disabled with :tags '(:slow))
+- liber-primus.txt (corpus file, may need size optimization)
+
+**Success Criteria:**
+- Text generation completes in reasonable time
+- Benchmark tests run in < 5 seconds
+- Tests can be re-enabled without blocking test suite
+
+Priority [#D] because it's not breaking workflow, just slower than ideal.
+
+
+*** TODO [#D] Optimize size of liber-primus.txt for lorem-optimum and investigate launch notices
+
+The liber-primus.txt file may be too large for optimal lorem-optimum performance,
+causing slow random text generation or excessive memory usage. Additionally, there
+are notices appearing in the *Messages* buffer during Emacs launch that need investigation.
+
+**Primary Problem:**
+- liber-primus.txt might be too large for efficient text generation
+- lorem-optimum may be slow when selecting random text from large corpus
+- File size could be causing memory or performance issues
+- Impact on startup time or buffer creation unknown
+
+**Secondary Problem:**
+- *Messages* buffer shows notices during Emacs launch
+- May be related to lorem-optimum, liber-primus, or unrelated issues
+- Need to identify source and severity of notices
+
+**Investigation:**
+
+1. **Check current file size:**
+ ```bash
+ ls -lh liber-primus.txt
+ wc -l liber-primus.txt
+ wc -w liber-primus.txt
+ ```
+
+2. **Review lorem-optimum configuration:**
+ - Find lorem-optimum module: `grep -r "lorem-optimum" modules/`
+ - Check how liber-primus.txt is loaded
+ - Look for performance issues in implementation
+ - Check if entire file is loaded into memory
+
+3. **Test performance with current file:**
+ ```elisp
+ (benchmark-run 100
+ (lorem-ipsum-insert-paragraphs 1))
+ ```
+ - Measure baseline performance
+ - Note memory usage
+
+4. **Investigate Messages buffer notices:**
+ - Launch Emacs with `emacs --debug-init`
+ - Check *Messages* buffer immediately after startup
+ - Search for lorem, liber-primus, or warning keywords
+ - Note timestamps and context
+
+5. **Identify notices source:**
+ - Could be from lorem-optimum loading
+ - Could be file permissions warnings
+ - Could be encoding issues
+ - Could be unrelated initialization messages
+
+**Possible Solutions:**
+
+1. **Reduce file size** (if too large):
+ - Keep most meaningful/interesting sections
+ - Remove repetitive content
+ - Target size: 50-100KB (fast loading, sufficient variety)
+ - Preserve character of cryptic/cipher text
+
+2. **Optimize lorem-optimum loading** (if implementation issue):
+ - Lazy load: don't read file until first use
+ - Sample lines: don't load entire file
+ - Cache in memory: read once, reuse
+ - Stream reading: read chunks as needed
+
+3. **Fix launch notices** (if errors/warnings):
+ - Fix source of warnings
+ - Silence benign notices
+ - Add proper error handling
+ - Document expected behavior
+
+**Testing:**
+1. Note baseline: file size, performance, messages
+2. Apply optimization (file size or code)
+3. Measure improvement:
+ - File size reduced?
+ - Performance improved?
+ - Messages cleaned up?
+4. Verify text generation still works
+5. Check variety/quality of generated text
+
+**Related Files:**
+- liber-primus.txt (the text corpus file)
+- modules/lorem-optimum.el or similar (lorem generation module)
+- init.el (loading sequence, Messages source)
+- tests/test-lorem-optimum-*.el (performance/benchmark tests)
+
+**Related Docs:**
+- DONE task at line 68-96: "Review lorem-optimum benchmark tests and fix"
+- Failed benchmark tests may be related to this issue
+- V2MOM Method 1: Frictionless (fast text generation)
+- V2MOM Method 2: Stop Problems Before They Appear (clean Messages)
+
+**Success Criteria:**
+- liber-primus.txt optimized to reasonable size (<100KB ideal)
+- lorem-optimum generates text quickly (<100ms for paragraph)
+- No unnecessary notices in *Messages* during launch
+- Text generation still produces varied, interesting output
+- Benchmark tests pass (after fixing per separate TODO)
+- Documented optimal file size and loading strategy
+
+**Benchmark Target:**
+- Text generation: <100ms for 1 paragraph
+- File loading: <50ms at startup (if not lazy loaded)
+- Memory usage: Reasonable for file size
+- No degradation from current working state
+
+**Note:**
+Priority [#B] because performance impacts daily workflow (lorem text generation
+used frequently for testing) and clean *Messages* buffer is important for catching
+real issues during startup. This ties into fixing the 2 failed benchmark tests
+(separate TODO at line 68-96).
+
+* Method 4: Contribute to the Emacs Ecosystem [0/4]
+** TODO [#C] Integrate undercover.el for test coverage
+
+Measure and track test coverage over time.
+
+** TODO [#C] Set up melpazoid CI for MELPA submissions
+
+Validates packages meet MELPA standards.
+
+** TODO [#C] Set up package-lint for elisp linting (chime, org-msg, wttrin)
+
+Catch packaging issues automatically.
+
+** TODO [#C] Set up elisp-check GitHub Action
+
+Zero-config CI for Emacs packages.
+
+* Method 5: Be Kind To Your Future Self [1/2]
+** DONE [#C] Add transcription workflow
+CLOSED: [2025-11-12 Wed 02:41]
+:PROPERTIES:
+:COMPLETE_CONFIG: [[file:docs/someday-maybe.org::2][todo.org:2-99]]
+:END:
+
+Complete code already exists in someday-maybe.org. Need today and recurring.
+
+** DONE [#A] Implement org-reveal presentation workflow
+CLOSED: [2026-02-14 Fri]
+
+Created org-reveal-config.el module with ox-reveal integration for offline,
+self-contained reveal.js presentations. Keybindings under C-; p prefix.
+Removed pandoc-based reveal.js export from org-export-config.el.
+
+** TODO [#B] Create custom dupre reveal.js theme
+
+Create a custom reveal.js CSS theme using colors from themes/dupre-palette.el.
+Install into reveal.js/css/theme/ for use with #+REVEAL_THEME: dupre.
+
+** TODO [#B] Investigate missing yasnippet configuration
+
+snippets-dir is defined in user-constants.el (points to org-dir/snippets/) and
+yasnippet is configured in prog-general.el, but no custom snippets directory or
+snippet files exist. Investigate whether snippets should be created (e.g., org
+structure templates for reveal.js headers, blog post front matter, etc.).
+
+* Method 6: Develop Disciplined Engineering Practices [1/3]
+** TODO [#C] Track current metrics baseline
+
+- [ ] Measure current startup time (time emacs --eval '(save-buffers-kill-emacs)')
+- [ ] Count current active todos
+- [ ] Set up tracking document for weekly metrics
+
+** TODO [#C] Set up monthly research:shipped ratio tracking
+
+Can't research next thing until current thing is implemented.
+
+** DONE [#A] First weekly triage by Sunday (establish habit)
+CLOSED: [2025-11-12 Wed 02:41] SCHEDULED: <2025-11-03 Sun>
+
+Review this inbox, cancel stale items, keep < 20 active. Track in calendar.
+
+* Emacs Config Inbox
+** VERIFY [#B] Continue org-noter custom workflow implementation (IN PROGRESS)
+
+Continue debugging and testing the custom org-noter workflow from 2025-11-21 session.
+This is partially implemented but has known issues that need fixing before it's usable.
+
+**Last worked on:** 2025-11-21
+**Current status:** Implementation complete but has bugs, needs testing
+
+**Known Issues to Fix:**
+
+1. **Double notes buffer appearing when pressing 'i' to insert note**
+ - When user presses 'i' in document to insert a note, two notes buffers appear
+ - Expected: single notes buffer appears
+ - Need to debug why the insert-note function is creating duplicate buffers
+
+2. **Toggle behavior refinement needed**
+ - The toggle between document and notes needs refinement
+ - May have edge cases with window management
+ - Need to test various scenarios
+
+**Testing Needed:**
+
+1. **EPUB files** - Test with EPUB documents (primary use case)
+2. **Reopening existing notes** - Verify it works when notes file already exists
+3. **Starting from notes file** - Test opening document from an existing notes file
+4. **PDF files** - Verify compatibility with PDF workflow
+5. **Edge cases:**
+ - Multiple windows open
+ - Splitting behavior
+ - Window focus after operations
+
+**Implementation Files:**
+- modules/org-noter-config.el - Custom workflow implementation
+- Contains custom functions for document/notes toggling and insertion
+
+**Context:**
+This custom workflow is designed to make org-noter more ergonomic for Craig's reading/annotation
+workflow. It simplifies the toggle between document and notes, and streamlines note insertion.
+The core functionality is implemented but needs debugging before it's production-ready.
+
+**Next Steps:**
+1. Debug the double buffer issue when pressing 'i'
+2. Test all scenarios listed above
+3. Refine toggle behavior based on testing
+4. Document the final keybindings and workflow
+
+** TODO [#D] Add status dashboard for dwim-shell-command processes
+
+Create a command to show all running dwim-shell-command processes with their status.
+Currently, there's no unified view of multiple running extractions/conversions.
+
+**Current behavior:**
+- Each command shows spinner in minibuffer while running
+- Process buffers created: `*Extract audio*`, etc.
+- On completion: buffer renamed to `*Extract audio done*` or `*Extract audio error*`
+- No way to see all running processes at once
+
+**Implementation approaches:**
+
+1. **Use existing process list (simplest):**
+ - Enhance `M-x list-processes` output filtering
+ - Create wrapper command that filters to dwim-shell processes only
+ - Pro: Uses built-in functionality
+ - Con: Generic process list, not tailored
+
+2. **Custom status buffer:**
+ - Create command `dwim-shell-commands-status` or similar
+ - Access `dwim-shell-command--commands` variable (tracks all running commands)
+ - Display in custom buffer with:
+ - Command name
+ - Files being processed
+ - Progress/status
+ - Time running
+ - Allow actions: view buffer, kill process
+ - Pro: Tailored UI, more useful information
+ - Con: More code to maintain
+
+3. **Mode-line indicator:**
+ - Show count of running dwim commands in mode-line
+ - Click to open status buffer
+ - Pro: Always visible, lightweight
+ - Con: Limited information at a glance
+
+**Recommended approach:**
+Start with option 2 (custom status buffer) that reads `dwim-shell-command--commands`.
+Can add mode-line indicator later as enhancement.
+
+**Files to create/modify:**
+- modules/dwim-shell-config.el - add status command
+
+** TODO [#C] Create print function for dirvish bound to uppercase P
+
+Add a print function that works on printable files (PDF, txt, org, etc.) and bind it to uppercase P in dirvish-mode. Should detect file type and use appropriate print command (lpr for text files, print dialog for PDFs, etc.).
+
+** TODO [#C] Review and implement flycheck modeline customization spec
+
+Add flycheck status (error/warning counts) to custom modeline to make it visible again.
+
+**Spec Document:**
+[[file:docs/flycheck-modeline-customization-spec.org][flycheck-modeline-customization-spec.org]]
+
+**Summary:**
+Current custom modeline excludes minor-mode-alist where flycheck displays its status.
+Need to either:
+1. Add flycheck's lighter directly to mode-line-format (simplest)
+2. Customize flycheck prefix/indicator and add to modeline
+3. Create custom flycheck segment with full control
+
+**Files to Modify:**
+- modules/flycheck-config.el (customize prefix/indicator)
+- modules/modeline-config.el (add to mode-line-format)
+
+**Emoji Options:**
+- Prefix: 🪰 (fly), 🐛 (bug), ✓ (check), ⚠ (warning), 🔍 (magnifier)
+- Success: ✓, ✅, 🟢, ✨, 💯
+
+**Recommended Approach:**
+Option 4 (Hybrid) from spec - customize flycheck variables + add to modeline.
+Simple, maintainable, respects flycheck's built-in logic.
+
+**Next Steps:**
+1. Review spec document and choose emoji combination
+2. Add customization to flycheck-config.el
+3. Add to modeline-config.el mode-line-format
+4. Test in sh-mode and emacs-lisp-mode buffers
+
+** TODO [#C] Investigate TRAMP/dirvish showing question marks for file dates
+
+Remote directories in dirvish show "?" instead of actual modification dates.
+Tried several approaches without success - needs deeper investigation.
+
+**Attempted fixes (all reverted):**
+1. Connection-local dired-listing-switches with -alh (didn't help)
+2. Disabling tramp-direct-async-process (reported to cause this, but disabling didn't fix it)
+3. Hook to set different listing switches for remote vs local (didn't help)
+
+**Possible causes to investigate:**
+- dirvish may be using its own attribute fetching that bypasses dired-listing-switches
+- May need dirvish-specific configuration for remote file attributes
+- Could be an Emacs 29/30 + TRAMP + dirvish interaction issue
+- May require changes to how dirvish renders the file-size attribute on remote
+
+**Resources:**
+- https://github.com/alexluigit/dirvish/discussions/124 (related TRAMP issues)
+- https://github.com/alexluigit/dirvish/blob/main/docs/CUSTOMIZING.org (TRAMP section)
+
+**Files involved:**
+- modules/tramp-config.el
+- modules/dirvish-config.el
+
+**Workaround:**
+Use regular dired for remote directories if timestamps are needed.
+
+* TODO [#B] Review and rebind M-S- keybindings
+Changed from M-uppercase to M-S-lowercase for terminal compatibility.
+These may override useful defaults - review and pick better bindings:
+- M-S-b calibredb (was overriding backward-word)
+- M-S-c time-zones (was overriding capitalize-word)
+- M-S-d dwim-shell-menu (was overriding kill-word)
+- M-S-e eww (was overriding forward-sentence)
+- M-S-f fontaine (was overriding forward-word)
+- M-S-h split-below
+- M-S-i edit-indirect
+- M-S-k show-kill-ring (was overriding kill-sentence)
+- M-S-l switch-themes (was overriding downcase-word)
+- M-S-m kill-all-buffers
+- M-S-o kill-other-window
+- M-S-r elfeed
+- M-S-s window-swap
+- M-S-t toggle-split (was overriding transpose-words)
+- M-S-u winner-undo (was overriding upcase-word)
+- M-S-v split-right (was overriding scroll-down)
+- M-S-w wttrin (was overriding kill-ring-save)
+- M-S-y yank-media (was overriding yank-pop)
+- M-S-z undo-kill-buffer (was overriding zap-to-char)