diff options
| -rw-r--r-- | docs/SESSION-HANDOFF-ACTIVE-PROJECT.org | 263 | ||||
| -rw-r--r-- | docs/emacs-config-v2mom.org | 299 | ||||
| -rw-r--r-- | docs/values-comparison.org | 107 | ||||
| -rw-r--r-- | issues.org | 1879 |
4 files changed, 2548 insertions, 0 deletions
diff --git a/docs/SESSION-HANDOFF-ACTIVE-PROJECT.org b/docs/SESSION-HANDOFF-ACTIVE-PROJECT.org new file mode 100644 index 000000000..379b11a8e --- /dev/null +++ b/docs/SESSION-HANDOFF-ACTIVE-PROJECT.org @@ -0,0 +1,263 @@ +#+TITLE: 🚨 ACTIVE PROJECT - READ THIS FIRST 🚨 +#+AUTHOR: Claude Code Session Notes +#+DATE: 2025-10-30 + +* CURRENT PROJECT STATUS + +** 🎯 What We're Doing +Working through a systematic approach to clean up and prioritize Craig's Emacs config work: + +1. ✅ *COMPLETE V2MOM* (Vision, Values, Methods, Obstacles, Metrics) - IN PROGRESS +2. ⏳ *TRIAGE todo.org* - Use V2MOM to ruthlessly cancel ~60% of tasks +3. ⏳ *EXECUTE TIER 1* - Ship quick wins (network check removal, Corfu, bug fixes) +4. ⏳ *BUILD OBSERVABILITY* - Create profiling infrastructure (TIER 2) +5. ⏳ *SYSTEMATIC EXECUTION* - Work through prioritized tasks one by one + +** 📍 Where We Are Right Now +*Session Started:* 2025-10-30 +*Current Step:* V2MOM Methods section (60% complete - Vision + Values done) +*Time Committed:* ~1 hour sessions, working systematically +*Status:* PAUSED between sessions - resuming later this evening + +** 📄 Key Documents + +*** Primary Working Documents +- *V2MOM:* [[file:emacs-config-v2mom.org][emacs-config-v2mom.org]] - Strategic framework (ACTIVELY EDITING) +- *Issues Analysis:* [[file:../issues.org][../issues.org]] - Claude's detailed analysis with TIER system and implementations +- *Current Todos:* [[file:../todo.org][../todo.org]] - Craig's existing task list (~50+ items, needs triage) + +*** Reference Documents +- *Config Root:* [[file:../init.el][../init.el]] +- *Modules:* [[file:../modules/][../modules/]] +- *Tests:* [[file:../tests/][../tests/]] + +** 🔑 Key Insights About Craig's Work Patterns + +*** Strengths +- Thoughtful and strategic thinker +- Good research skills (thorough specs, complete code examples) +- Does ship things (dashboard, dirvish, network check fixes) +- Recognizes need for V2MOM framework +- Uses config daily for real work + +*** Patterns to Address +1. *Research > Execution* - Has complete code for Corfu, difftastic, transcription workflow... still TODO +2. *Priority Inflation* - Too many [#A]/[#B] items, unclear what's actually urgent +3. *Incomplete Strategy* - V2MOM structure exists but sections are empty +4. *Hard to Say No* - [#C]/[#D] items should be CANCELLED but remain in list +5. *Side Projects Compete* - Dupre theme work competes with core config maintenance + +*** What Craig Told Us About Himself +> "I am building tools both because they solve problems, but also because I enjoy building." + +This is healthy! But need balance: +- Fix rough edges FIRST (daily pain points) +- Build fun stuff SECOND (after maintenance) +- Cancel distractions ALWAYS (Signal client, minimap, etc.) + +** 🎯 Agreed Goals for This Project + +*** Immediate (Next 2-3 Sessions) +1. ✅ Complete V2MOM (IN PROGRESS) +2. ⏳ Triage todo.org using V2MOM as filter +3. ⏳ Execute quick wins: network check, Corfu migration, bug fixes +4. ⏳ Build debug-profiling.el infrastructure + +*** Short Term (Next Month) +5. Profile and optimize org-agenda performance +6. Ship reveal.js presentation workflow +7. Establish weekly triage ritual + +*** Long Term (Ongoing) +8. Ship more than research +9. Maintain < 20 active todos +10. Measure metrics from V2MOM + +** 📋 TIER System from issues.org + +*** TIER 1: Do These First (High Impact, Low Effort) - 1 weekend +- Remove network check (15 min) +- Fix missing functions (30 min) +- Corfu migration (2 hours) +- Mood-line switch (30 min) +- Bug fixes (1 hour) + +*** TIER 2: Build Observability (HIGHEST VALUE) - 1 week +- Create debug-profiling.el module (3-4 hours) +- Profile org-agenda-rebuild (1 hour) +- Add instrumentation and caching (2 hours) +- Test org-agenda filtering functions (2-3 hours) + +*** TIER 3: Quick Wins (After Profiling) - 1-2 hours each +- Reveal.js presentation workflow (2 hours) +- Difftastic integration (30 min) +- Local package development workflow (1 hour) + +*** TIER 4: Maybe/Someday (Probably Never) +- Code-maat reimplementation (HOLD) +- LaTeX config (HOLD until concrete need) +- Elfeed dashboard (HOLD - unclear if actually used) +- DWIM shell integration (HOLD - current solution works) +- Jumper package (HOLD - already maintaining chime + org-msg) + +** 🚫 Items That Should Be CANCELLED + +From todo.org, these don't serve the vision: +- [#D] Signal Client - Not in vision +- [#D] Awesome-tray / mode-icons - Already have modeline +- [#C] Minimap - Interesting, not important +- [#C] Install Magit TODOs - Already works fine +- [#C] Git Timemachine litters buffers - Minor annoyance +- Many Dupre theme TODOs - Side project competing with maintenance + +## 💡 Key Recommendations for Craig + +### Week 1: Strategy + Quick Wins +1. Complete V2MOM (2-3 hours) +2. Triage todo.org using V2MOM (1-2 hours) +3. Execute items you already have code for (2-3 hours) + +### Week 2: Observability Infrastructure +4. Build debug-profiling.el (3-4 hours) +5. Profile org-agenda (1 hour) + +### Week 3: Fix Performance + Ship Presentation +6. Fix org-agenda based on profiling (2-3 hours) +7. Ship reveal.js workflow (2 hours) + +### Ongoing: Maintenance Discipline +- Weekly triage ritual (30 min every Sunday) +- Measure metrics (startup time, agenda time, todo count) +- Ship > Research + +** 🔄 Next Session Pickup Points + +When starting next session, Claude should: + +1. **Read this document first** to understand context +2. **Check V2MOM status** - If incomplete, continue there +3. **Reference issues.org** for detailed technical recommendations +4. **Reference todo.org** for items to triage +5. **Ask Craig:** "Where did we leave off? V2MOM? Triage? Execution?" + +** 📞 Questions to Ask Craig Next Session + +*IMMEDIATE (when resuming):* +- "Ready to continue V2MOM? We left off at Methods section." +- "How much time do you have?" + +*FOR METHODS SECTION:* +Show Craig the draft list and ask: +- "Which methods do you already do consistently?" +- "Which do you want to do but don't yet?" +- "Am I missing any important methods?" + +*AFTER V2MOM COMPLETE:* +- "Ready to triage todo.org using the V2MOM?" +- "Should we execute quick wins or continue systematic triage?" + +** 🎯 Success Metrics for This Project + +We'll know this is working when: +- ✅ V2MOM is complete and provides clear strategic direction +- ✅ todo.org shrinks from ~50 to < 20 active items +- ✅ Craig ships 3-5 items per week (small but consistent) +- ✅ Craig has profiling infrastructure to measure performance +- ✅ Org agenda rebuild time is measured and improving +- ✅ Weekly triage becomes habit + +** 💬 Craig's Words to Remember + +> "I think you should adjust issues.org with all your recommendations. They are exciting, eye-opening, and just feel right. Add even your guidance on latex. spot on. thanks for your honesty. I did ask for it and am genuinely grateful for your responses. I'll take action on them." + +> "What I need help with is integrating this in with my existing todo.org file... Some of the tasks I've listed should probably just be deleted or better yet, marked CANCELLED." + +> "I have about an hour to devote. You could lead me through it, I could do some questions/answer rounds with you to clarify my thinking." + +Craig is ready to execute. He asked for honesty and took it well. He recognizes the patterns and wants systematic help. + +** 🛠️ Technical Context + +*** Current Pain Points +1. Org agenda is slow (performance bottleneck) +2. Network check adds 1+ seconds to startup (technical debt) +3. Missing functions cause errors (cj/log-silently, cj/goto-git-gutter-diff-hunks) +4. Mail attachments workflow is awkward +5. No profiling infrastructure to measure performance + +*** Items Craig Already Has Code For +These can be executed immediately - just paste and test: +- Transcription workflow (complete bash + elisp in todo.org:2-99) +- Difftastic integration (complete config in todo.org:1211-1223) +- Corfu migration (complete config in todo.org:1611-1639) + +*** Architecture +- Modular structure: modules/*.el +- Good test coverage for utilities +- Modern packages: Vertico/Consult/Embark stack +- Local package development: chime.el, org-msg + +** 📚 Related Reading + +If Craig or Claude need more context: +- [[file:../issues.org::*Second Opinion: Ruthless Prioritization & Reality Checks][Second Opinion section in issues.org]] - Full analysis and recommendations +- [[file:../issues.org::*TIER 1: Do These First][TIER 1-4 breakdown]] - Prioritized task system +- [[file:../quality-engineer.org][quality-engineer.org]] - Testing philosophy (if exists) + +** 🚀 Current Session Notes + +*** 2025-10-30 Session 1 - V2MOM In Progress +*Time:* ~1 hour +*Status:* PAUSED - V2MOM 60% complete + +*What We Completed:* +1. ✅ Created docs/ directory structure +2. ✅ Created SESSION-HANDOFF-ACTIVE-PROJECT.org (this file) +3. ✅ Created emacs-config-v2mom.org +4. ✅ Created values-comparison.org (analysis doc) +5. ✅ Completed Vision (already existed, kept as-is) +6. ✅ Completed Values section (Intuitive, Fast, Simple) + - Intuitive: Muscle memory, mnemonics, which-key timing, "newspaper" code + - Fast: Startup < 2s, org-agenda is THE bottleneck, everything else acceptable + - Simple: Production software practices, simplicity produces reliability + +*What's Next:* +1. ⏳ *Methods* - IN PROGRESS (have draft list, need Craig's input) +2. ⏳ *Obstacles* - TODO +3. ⏳ *Metrics* - TODO +4. ⏳ *Finalize V2MOM* - Review and commit + +*Draft Methods List (Need Craig's Feedback):* +These were proposed but Craig stopped before reviewing: +1. Ruthless prioritization (V2MOM guides triage) +2. Profile before optimizing (build observability first) +3. Test-driven development (tests enable confident refactoring) +4. Ship > Research (execute existing specs before exploring new) +5. Weekly triage ritual (review todos, cancel stale, keep < 20 active) +6. Measure metrics (track startup, agenda, test coverage, todo count) +7. Extract packages (when custom code grows: chime, org-msg pattern) +8. Incremental execution (ship small, test, iterate) + +*Questions to Ask Craig When Resuming:* +- Which methods do you already do consistently? +- Which do you want to do but don't yet? +- Am I missing any important methods? + +*After Methods/Obstacles/Metrics Complete:* +Then move to triage todo.org using completed V2MOM as filter. + +*Key Files Modified This Session:* +- [[file:emacs-config-v2mom.org][emacs-config-v2mom.org]] - Main working document (60% complete) +- [[file:values-comparison.org][values-comparison.org]] - Analysis doc (reference only) +- [[file:SESSION-HANDOFF-ACTIVE-PROJECT.org][SESSION-HANDOFF-ACTIVE-PROJECT.org]] - This file + +*Next Session Starts With:* +1. Read this handoff document +2. Read emacs-config-v2mom.org to see what's complete +3. Ask Craig: "Ready to continue V2MOM with Methods section?" +4. Show Craig the draft Methods list +5. Get feedback and complete Methods +6. Move to Obstacles +7. Move to Metrics +8. Finalize V2MOM +9. Then triage todo.org diff --git a/docs/emacs-config-v2mom.org b/docs/emacs-config-v2mom.org new file mode 100644 index 000000000..066641034 --- /dev/null +++ b/docs/emacs-config-v2mom.org @@ -0,0 +1,299 @@ +#+TITLE: Emacs Configuration V2MOM +#+AUTHOR: Craig Jennings +#+DATE: 2025-10-30 +#+FILETAGS: :strategy:planning:v2mom: + +* What is V2MOM? + +V2MOM is a strategic framework used to clarify goals and priorities: +- *Vision:* What do you want to achieve? +- *Values:* What principles guide decisions? +- *Methods:* How will you achieve the vision? +- *Obstacles:* What's in your way? +- *Metrics:* How will you measure success? + +This document provides strategic clarity for prioritizing Emacs configuration work. + +* Vision + +Your personal ideal Emacs configuration allows you to work at the speed of your own thought. It's stable and never needs edge-case bug fixing. The functionality covers your workflow such that you can work all day in Emacs for any of the following task areas: + +- Programming in any language, including emacs-lisp, common-lisp, scheme, golang, and c +- Reading ebooks, including marginalia handling +- Listening to music, including playlist management +- Listening to podcasts, including saving episodes +- Task organizing and planning +- Calendaring, including syncing with google calendar +- Alerting and notifications on tasks and calendar events +- Timer/stopwatch functionality, including pomodoro presets +- Audio and desktop recording +- Memorization drills +- Email, including email-to-task integration +- Messaging, i.e., IRC +- File-management, including extensive integration, and DWM scratchpad integration outside Emacs +- Shell commands, leveraging vterm and eshell with custom methods, and DWM scratchpad integration outside Emacs + +Anytime you make a change in the config, you have unit tests to tell you quickly if the change created unexpected issues. You have a test-runner that integrates with your workflow. + +* Values + +** Intuitive + +*Definition:* Intuition comes from muscle memory, clear mnemonics, and just-in-time discovery that reinforces learning without blocking productivity. + +*** Keybindings Build Intuition Through Layers +1. *Muscle memory first* - C-; on home row becomes automatic habit +2. *Mnemonics provide "aha!" moments* - C-c **m** for mail creates dopamine hits that cement permanent memory +3. *Which-key teaches through active recall* - Appears after you try (not before), forcing attempt without wasting time + +The timing matters: which-key's delay is calibrated so you're challenged to remember, but not blocked from working. + +*** What Breaks Intuition +- *Physically awkward keybindings* - C-c 1 z C-c f requires hand contortions and offers no mnemonic +- *Syntax overhead* - Parentheses tracking steals time from real learning (logic bugs, architecture understanding) +- *Poor architecture* - Common actions (like "save all attachments") shouldn't require architectural archaeology + +*** Code Reads "Like a Newspaper" +- Each use-package declaration is a *story* (topic = package) +- Configuration settings are *facts* (what it does, how it behaves) +- Clear variable/method naming (yours + maintainers) makes code read like English +- Accessible to intermediate elisp readers without deep archaeology + +*** Principle +*Intuition is earned through repeated success, not instant magic.* The config should make success easy to achieve and memorable when it happens. + + + +** Fast + +*Definition:* Fast means staying in flow. Startup and org-agenda must not make me wait. Everything else is already acceptable. + +*** Performance Targets + +*Startup Time:* +- Current: ~3.8 seconds (real clock time, not Emacs-reported) +- Target: ~1 second (aspirational, may not be realistic given package count) +- Comfortable: ~2 seconds (±) + +*Measurement:* +#+begin_src bash +time emacs --eval '(save-buffers-kill-emacs)' # Real startup time +#+end_src + +*Note:* Emacs-reported time is inaccurate. Messages buffer continues populating and Emacs remains unresponsive after "loaded" message appears. + +*** Critical Performance Issues (Must Fix) + +1. *Emacs startup* - 3.8s is too slow + - Network check adds 1+ seconds (DELETE THIS) + - Eager loading vs lazy loading + +2. *Opening org-agenda for first time* - **THE BOTTLENECK** + - "Takes forever and a full work day" + - Likely: recursive directory scan, no caching, too many files + - Solution: Profile first (build debug-profiling.el), then optimize + +*** Must Be Instant (Flow-Critical) +- Keybinding response +- Changing projects in projectile (already good ✓) +- Opening large org files (already good ✓, except malformed files with stray "*"s) +- Buffer/window operations + +*** Can Take 1-2 Seconds (Acceptable) +- *Mail sync* - Consider putting on timer instead of manual trigger +- *Calibredb* (PDFs/Epubs) - Known solution: shrink inventory to <1k books or contribute optimizations +- *Org-noter* opening PDFs/Epubs - Needs reliability + reasonable speed +- *Looking up org-noter notes* - Should be easy to pull into other documents +- *Initial file indexing* (projectile, etc.) + +*** Disabled Due to Performance (Need Solutions) +- *Grammar checker* - Installed but turned off because it slows everything down + - No task exists to fix this yet + - Breaks concentration when writing + +- *Bibliography management* - Don't know how to do in Emacs + - Worried about broken/slow tools breaking writing flow + - Need solution that "just works" + +*** Principle +*Speed is about flow, not milliseconds.* Startup and agenda are flow-breakers. Everything else is fine. Don't optimize what doesn't hurt. + + + +** Simple + +*Definition:* Simple means clear, maintainable code following production software practices. Simplicity is a discipline that produces reliability. Config is production software - treat it as such. + +*** What Makes Code Simple +1. *Clear naming* - Variables and functions say what they do +2. *Small functions* - Easy to understand, test, and modify +3. *Good comments* - NOT obvious comments ("cat with post-it note saying 'cat'") + +*Good comments:* +- Navigation markers for long files +- Explain complex/non-obvious logic +- Document unobvious impacts of settings +- Answer "why" not "what" + +*Bad comments:* +#+begin_src emacs-lisp +;; declare a variable +(defvar variable 10) +#+end_src + +*** Abstractions and Magic +- *Abstractions are fine* if they serve a purpose +- *Macros are irritating* when unnecessary, but acceptable when warranted +- *Magic is acceptable* if it's reliable and you can build a mental model + +*Principle:* "I want to understand every line of what my config does, or at least have a decent mental model of how it probably works. Never use a tool you can't fully trust." + +*** Package Count +Package count itself isn't a concern. Quality and maintainability matter. + +*Concerns:* +- More packages = more potential breakage +- Need ability to roll back when packages break (localrepo for package snapshots) +- Maintenance burden is real, but manageable with good practices + +*Not concerned about:* +- Absolute number of packages +- Startup time impact (if lazy-loaded properly) +- Cognitive load (if organized well) + +*** Config IS Production Software + +*Key insight:* "My Emacs config IS production software. I use it more than probably every other application combined. The impact when it's broken can crush my productivity." + +This means: +- *Apply production practices:* Testing, modularity, documentation, version control +- *Plan for failure:* Rollback capability (localrepo), error handling, graceful degradation +- *Modular design:* Extract custom code into packages when it grows +- *Long-term maintenance:* Architecture matters, technical debt has real cost + +*** Personal Software Platform +"I see my config as a personal software project built on the software platform called Emacs. Emacs has taught me a great deal about how to build software platforms well." + +*Implications:* +- Config follows software engineering principles +- Custom functionality becomes packages (chime, org-msg, potentially jumper) +- Good architecture enables evolution +- Quality matters because uptime matters + +*** Why Simplicity Matters +When config breaks, productivity is crushed. The discipline of simplicity produces reliability: +- Simple code is easier to fix when it breaks +- Simple architecture enables graceful degradation +- Simple practices (testing, rollback) provide safety nets +- Simple means never using tools you can't trust + +*** Principle +*Simple means maintainable production software, not minimal or primitive.* Complexity is acceptable when it serves the vision and can be understood or trusted. **Simplicity is the practice that produces reliability as an outcome.** + + + +** Summary: Three Core Values + +1. *Intuitive* - Muscle memory, mnemonics, just-in-time discovery. Code reads like a newspaper. +2. *Fast* - Startup and org-agenda must not break flow. Everything else is acceptable. +3. *Simple* - Clear, maintainable, production-quality code. Simplicity produces reliability. + + + +* Methods + +#+begin_quote +Working section - HOW will you achieve the vision while honoring the values? + +*PAUSED HERE - NEED CRAIG'S INPUT* + +Draft methods proposed by Claude (need review): +1. Ruthless prioritization - V2MOM guides triage, cancel what doesn't serve vision +2. Profile before optimizing - Build observability (debug-profiling.el), measure first +3. Test-driven development - Tests give confidence to refactor, catch regressions +4. Ship > Research - Execute existing specs before exploring new ones +5. Weekly triage ritual - Review todos, cancel stale items, keep < 20 active +6. Measure metrics - Track startup time, agenda time, test coverage, todo count +7. Extract packages - When custom code grows, make it a package (chime, org-msg pattern) +8. Incremental execution - Ship small, test, iterate. Portions not all-at-once. + +*Questions for Craig:* +- Which of these do you already do consistently? +- Which do you want to do but don't yet? +- Am I missing any important methods? + +*Fill in below after discussion:* +#+end_quote + + + +* Obstacles + +#+begin_quote +Working section - What's preventing you from achieving the vision? + +*Questions to answer:* +- What technical challenges block you? +- What behavioral patterns get in your way? +- What external constraints limit you? +- What trade-offs are hardest to make? + +*Fill in below:* +#+end_quote + + + +* Metrics + +#+begin_quote +Working section - How will you know you're succeeding? + +*Questions to answer:* +- What numbers will you track? +- How will you measure performance? +- How will you measure productivity? +- What leading indicators show progress? + +*Fill in below:* +#+end_quote + + + +* How to Use This V2MOM + +** For Decision Making +When considering a new task, package, or feature: +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 → CANCEL the task. + +** For Triage +When reviewing todo.org: +- Tasks aligned with V2MOM → Keep and prioritize +- Tasks not aligned with V2MOM → CANCEL +- Tasks that are interesting but not important → CANCEL +- Tasks with complete code already → Execute immediately + +** For Weekly Review +Every Sunday (30 minutes): +1. Review metrics - Are they improving? +2. Review obstacles - Any new ones? Any resolved? +3. Review active todos - Still aligned with V2MOM? +4. Cancel stale/misaligned tasks +5. Plan next week's focus + +* Completion Status + +- [X] Vision - Complete (kept from original todo.org) +- [X] Values - Complete (Intuitive, Fast, Simple) +- [ ] Methods - IN PROGRESS (have draft, need Craig's input) +- [ ] Obstacles - TODO +- [ ] Metrics - TODO + +*Last Updated:* 2025-10-30 (Session 1) +*Next Session:* Continue with Methods section (review draft list with Craig) +*Estimated Time to Complete:* 20-30 minutes (Methods + Obstacles + Metrics) diff --git a/docs/values-comparison.org b/docs/values-comparison.org new file mode 100644 index 000000000..128c67103 --- /dev/null +++ b/docs/values-comparison.org @@ -0,0 +1,107 @@ +#+TITLE: Values Comparison - Simple vs Reliability +#+DATE: 2025-10-30 + +* What Currently Supports Each Value + +| Theme/Practice | Simple | Reliability | +|---------------------------------------+--------+-------------| +| *Code Quality* | | | +| Clear naming | ✓ | | +| Small functions | ✓ | | +| Good comments (why not what) | ✓ | | +| Abstractions when warranted | ✓ | | +|---------------------------------------+--------+-------------| +| *Architecture* | | | +| Modular design | ✓ | | +| Extract custom code into packages | ✓ | | +| Good architecture enables evolution | ✓ | | +| Technical debt has real cost | ✓ | | +|---------------------------------------+--------+-------------| +| *Production Practices* | | | +| Testing | ✓ | ✓ | +| Documentation | ✓ | | +| Version control | ✓ | | +|---------------------------------------+--------+-------------| +| *Failure Planning* | | | +| Rollback capability (localrepo) | ✓ | ✓ | +| Error handling | ✓ | ✓ | +| Graceful degradation | ✓ | ✓ | +|---------------------------------------+--------+-------------| +| *Trust & Stability* | | | +| Never use tools you can't trust | ✓ | ✓ | +| Uptime matters | | ✓ | +| Config breakage crushes productivity | | ✓ | +| More packages = more breakage risk | | ✓ | +| Need confidence to refactor | | ✓ | +|---------------------------------------+--------+-------------| + +* Key Quotes Supporting Each + +** Simple +- "Config IS production software - treat it as such" +- "Clear naming, small functions, good comments" +- "Apply production practices: Testing, modularity, documentation" +- "Simple means maintainable production software, not minimal or primitive" + +** Reliability/Resilience +- "Never use a tool you can't fully trust" +- "The impact when it's broken can crush my productivity" +- "More packages = more potential breakage. Need ability to roll back" +- "Plan for failure: Rollback capability, error handling, graceful degradation" +- "Quality matters because uptime matters" + +* Analysis + +** If Reliability is part of Simple: +*Simple means:* Maintainable, trustworthy, production-quality code that fails gracefully + +*Pros:* +- Keeps to 3 values +- Failure planning is a consequence of good engineering (already in Simple) +- Less redundancy + +*Cons:* +- "Simple" might not clearly convey the "must not break" urgency +- Rollback/resilience themes could get lost + +** If Reliability is its own value: +*Simple means:* Clear, maintainable code +*Reliability means:* Never breaks, fails gracefully, always recoverable + +*Pros:* +- Explicit focus on uptime/stability +- Clear that this is mission-critical (crushes productivity when broken) +- Resilience practices (localrepo, testing, error handling) have clear home + +*Cons:* +- 4 values instead of 3 +- Some overlap with Simple + +* Decision Framework + +Ask yourself: + +1. When choosing between two approaches, would "reliability" change your decision differently than "simple"? + + Example: Complex caching solution that's faster but harder to debug + - Simple says: "Too complex, harder to maintain" + - Reliability says: "If it breaks less often and has rollback, worth the complexity" + +2. Does "config can't break" deserve equal weight with Fast and Intuitive? + +3. Is the "trust" theme strong enough to be its own value? + +* Recommendation + +If you had to choose, I'd suggest: **Keep Simple, absorb Reliability into it.** + +Why? Most of your reliability practices (testing, rollback, error handling) are already listed under "production software practices" in Simple. The "never use tools you can't trust" is already there too. + +**But** - you could rename Simple to "**Reliable**" or "**Solid**" if the stability theme is more important than the simplicity theme. + +Alternative value names that might capture both: +- *Solid* - Stable, maintainable, trustworthy +- *Resilient* - Fails gracefully, recovers easily, maintainable +- *Dependable* - Simple enough to trust, robust enough to rely on + +What resonates? diff --git a/issues.org b/issues.org new file mode 100644 index 000000000..c61b85174 --- /dev/null +++ b/issues.org @@ -0,0 +1,1879 @@ +#+TITLE: Emacs Configuration Issues & Enhancement Roadmap +#+AUTHOR: Claude Code Analysis +#+DATE: 2025-10-30 + +* New Open Work + +** TODO [#A] Duplicate variable declaration in early-init.el :bug:architecture:critical: +:PROPERTIES: +:FILE: early-init.el +:LINES: 76-78, 104-105 +:END: + +The variable =cj/network-available= is declared twice (lines 76-78 and 104-105). + +*Impact:* Confusing code structure, potential initialization issues. + +*Fix:* Remove the duplicate declaration at lines 104-105. The first declaration at line 76 is sufficient. + +** TODO [#A] Missing function definition in vc-config.el :bug:critical: +:PROPERTIES: +:FILE: modules/vc-config.el +:LINE: 123 +:END: + +The keymap binding references =cj/goto-git-gutter-diff-hunks= (line 123) but this function is never defined anywhere in the config. + +*Impact:* Keybinding =C-; v d= will fail with "Symbol's function definition is void" error. + +*Fix:* Either implement the missing function or remove the keybinding. Likely should use =git-gutter:popup-hunk= or create a wrapper that calls =consult-line= filtered to lines with git-gutter markers. + +** TODO [#A] Missing function in wrap-up.el :bug:critical: +:PROPERTIES: +:FILE: modules/wrap-up.el +:LINE: 28 +:END: + +Calls =cj/log-silently= but function is never defined in the config. + +*Impact:* Init will fail at startup with undefined function error. + +*Fix:* Define =cj/log-silently= in system-defaults or config-utilities, or replace with a simple =(message ...)= call. + +** TODO [#A] Network check runs synchronously during startup :performance:critical: +:PROPERTIES: +:FILE: early-init.el +:LINES: 189, 206 +:END: + +The =cj/internet-up-p= function is called *synchronously* during early-init (lines 189, 206), which means Emacs startup blocks waiting for ping or network connection attempts. + +*Impact:* Adds 1+ seconds to every startup, even when network is available. Completely unacceptable UX. + +*Fix:* +1. Default =cj/network-available= to =t= (assume network is available) +2. Run network check asynchronously in background after startup +3. Only use network check when user explicitly runs =package-refresh-contents= +4. Consider removing network check entirely - let package.el handle its own errors + +Modern approach: Remove =cj/use-online-repos= flag entirely. Let package operations fail gracefully if network is down, rather than preemptively checking. + +** TODO [#A] Commented-out non-commented variable in org-config.el :bug:functionality: +:PROPERTIES: +:FILE: modules/org-config.el +:LINE: 129-130 +:END: + +Line 129 has a TASK comment about removing a non-existent variable =org-indent-indentation-per-level=, but line 130 actually tries to set it. + +*Impact:* Setting an undefined variable that does nothing. + +*Fix:* Remove lines 129-130 entirely if the variable doesn't exist. Verify in org-mode source whether this was renamed or removed. + +** TODO [#B] Replace Company with Corfu for better performance and maintenance :enhancement:architecture: +:PROPERTIES: +:FILE: modules/selection-framework.el +:LINES: 202-236 +:END: + +Currently using Company for completion, but Corfu is the more modern choice: + +*Why Corfu is better:* +- ~3x faster than Company (uses child frames vs overlays) +- Better maintained (company-mode development has slowed) +- Smaller, simpler codebase +- Works seamlessly with modern completion frameworks (Vertico/Consult) +- Native corfu-popupinfo is cleaner than company-quickhelp +- Better integration with Cape for completion-at-point backends + +*Migration path:* +1. Replace =company= with =corfu= + =corfu-popupinfo= +2. Use =cape= for additional backends (cape-file, cape-keyword, cape-dabbrev) +3. Keep company-mode disabled in mu4e (corfu already respects this) +4. Much simpler configuration, no company-box needed + +*Estimated effort:* 30 minutes. High value/low effort. + +** TODO [#B] Consolidate debug logging functions :architecture:maintainability: +:PROPERTIES: +:FILES: modules/org-agenda-config-debug.el, modules/wrap-up.el +:END: + +Debug logging is inconsistent: +- =org-agenda-config-debug.el= defines =cj/log-silently= +- =wrap-up.el= *calls* =cj/log-silently= but it's not loaded yet +- =config-utilities.el= has debug functions but not logging + +*Fix:* Create =modules/debug-logging.el= with consistent logging infrastructure: +- =cj/log-debug=, =cj/log-info=, =cj/log-warning=, =cj/log-error= +- Buffer-based logging with timestamps +- Easy toggle for debug mode +- Load early in init.el before other modules + +** TODO [#B] Missing error handling in org-agenda rebuild :stability: +:PROPERTIES: +:FILE: modules/org-agenda-config.el +:LINES: 91-105 +:END: + +=cj/build-org-agenda-list= recursively searches directories but has no error handling for: +- Permission denied errors +- Circular symlinks +- Very deep directory trees +- Network filesystem timeouts (if projects-dir is on NFS/CIFS) + +*Impact:* Agenda rebuild can hang or fail silently. + +*Fix:* Add condition-case wrapper with specific handlers: +#+begin_src elisp +(condition-case err + (cj/add-files-to-org-agenda-files-list projects-dir) + (file-error + (message "Warning: Could not scan %s: %s" projects-dir err)) + (error + (message "Error building agenda: %s" err))) +#+end_src + +** TODO [#B] Unify path handling functions :architecture:maintainability: +:PROPERTIES: +:FILES: modules/dirvish-config.el, modules/custom-buffer-file.el +:END: + +Path handling is duplicated across modules: +- =cj/get-project-root= in dirvish-config.el (lines 408-426) +- Similar logic needed in custom-buffer-file for relative paths +- Different approaches to home directory abbreviation + +*Fix:* Create =modules/path-utils.el= with: +- =cj/get-project-root= (shared implementation) +- =cj/abbreviate-path= (handles ~, project-relative, absolute) +- =cj/path-relative-to= (generalized relative path function) +- Consistent path handling across all modules + +** TODO [#B] Treesit-auto grammar pinning is fragile :stability:maintenance: +:PROPERTIES: +:FILE: modules/prog-general.el +:LINES: 106-113 +:END: + +Go grammar is pinned to v0.19.1 by directly modifying the treesit-auto-recipe-list vector with =aset=. + +*Issues:* +- Hardcoded slot index (6) will break if treesit-auto changes struct layout +- No validation that the recipe exists or that slot 6 is :revision +- Comment says "Emacs 30.2" but doesn't check version +- Will fail silently if treesit-auto changes + +*Fix:* +1. Use proper accessor functions if available (treesit-auto-recipe-revision setter) +2. Add version check: =(when (version< emacs-version "30.3") ...)= +3. Add error handling and warning if pinning fails +4. Document why pinning is needed in comments + +** TODO [#B] Test coverage gaps in critical modules :testing:quality: +:PROPERTIES: +:FILES: modules/org-agenda-config.el, modules/mail-config.el, modules/ai-config.el +:END: + +Excellent test coverage for utility functions (custom-*, undead-buffers, org-roam helpers), but missing tests for: + +*High-value untested areas:* +1. =org-agenda-config.el=: + - =cj/build-org-agenda-list= (file discovery logic) + - =cj/org-skip-subtree-if-*= functions (agenda filtering) + - =cj/org-agenda-skip-subtree-if-not-overdue= (date logic) + +2. =mail-config.el=: + - =cj/mu4e-toggle-remote-images= (security critical) + - Email header parsing/address completion logic + +3. =ai-config.el=: + - =cj/gptel-add-file= (file path handling) + - =cj/gptel--fresh-org-prefix= (timestamp formatting) + +4. =org-roam-config.el=: + - =cj/move-org-branch-to-roam= (complex string manipulation) + - Already has tests for helpers, needs integration test + +*Recommendation:* Prioritize testing the org-agenda filtering functions - they're date-sensitive and easy to break. + +** TODO [#B] System-defaults autoload has wrong function name :bug:minor: +:PROPERTIES: +:FILE: modules/system-defaults.el +:LINE: 24 +:END: + +Line 24 has =autoload= for =env-bsd-p= from =host-environment=, but this file *requires* host-environment at compile time anyway (line 20). + +*Impact:* Redundant autoload, no functional issue. + +*Fix:* Remove the autoload statement. The eval-when-compile require is sufficient. + +** TODO [#B] Inconsistent coding system declarations :maintainability: +:PROPERTIES: +:FILES: early-init.el, modules/system-defaults.el +:END: + +UTF-8 coding system is set in two places: +- =early-init.el= lines 252-261 (before package loading) +- =system-defaults.el= lines 60-69 (after package loading) + +*Impact:* Redundant configuration, harder to maintain, unclear which takes precedence. + +*Fix:* Consolidate all coding system setup in early-init.el since it needs to be set before packages load. Remove from system-defaults.el. + +** TODO [#B] Chime notification times documentation mismatch :documentation:usability: +:PROPERTIES: +:FILE: modules/org-agenda-config.el +:LINES: 268-270 +:END: + +Comment says "5 minutes before and at event time (0 minutes)" but the value is ='(5 0)=. + +*Issue:* It's unclear if 0 means "at event time" or "immediately". Better documentation needed. + +*Fix:* Improve comment: +#+begin_src elisp +;; Alert 5 minutes before event and again at event time (0 = event start) +(setq chime-alert-time '(5 0)) +#+end_src + +** TODO [#C] Org-roam template paths use string concatenation :maintainability: +:PROPERTIES: +:FILE: modules/org-roam-config.el +:LINES: 43, 48, 53, 144, 150 +:END: + +Template file paths are built with =concat= instead of using =expand-file-name= or constants. + +*Impact:* Harder to change template location, no validation that files exist. + +*Fix:* Define template constants at top of file: +#+begin_src elisp +(defconst cj/org-roam-template-dir + (expand-file-name "org-roam-templates" user-emacs-directory)) +(defconst cj/org-roam-template-v2mom + (expand-file-name "v2mom.org" cj/org-roam-template-dir)) +;; etc... +#+end_src + +Validate files exist during config load. + +** TODO [#C] Dirvish-config has long function that should be split :refactor:maintainability: +:PROPERTIES: +:FILE: modules/dirvish-config.el +:LINES: 350-406 +:END: + +=cj/dired-copy-path-as-kill= is 57 lines with multiple responsibilities: +- Validation +- Project root detection +- Home directory handling +- Org-link formatting +- Clipboard operations +- User feedback + +*Fix:* Extract smaller functions: +- =cj/--path-type-for-file= (returns :project-relative, :home-relative, or :absolute) +- =cj/--format-as-org-link= (wraps path in org syntax) +- =cj/dired-copy-path-as-kill= (orchestrates the above) + +Better testability, clearer logic flow. + +** TODO [#C] Consider Embark for file operations instead of custom dirvish bindings :enhancement:usability: +:PROPERTIES: +:FILE: modules/dirvish-config.el +:LINES: 298-334 +:END: + +Dirvish config defines many custom keybindings (d, l, L, o, O, f, P) for file operations. + +*Alternative approach:* Use Embark for contextual file actions: +- Embark already knows about files in dired +- Can define actions once, use everywhere (not just dired) +- More discoverable (embark-act shows all options) +- Less cognitive load (one keybinding to remember: C-.) + +*Recommendation:* Keep the custom functions (good implementations), but expose them via embark-act instead of direct keybindings. Cleaner keymap, more flexible. + +** TODO [#C] Missing :ensure nil for more built-in packages :correctness:minor: +:PROPERTIES: +:FILE: Multiple modules +:END: + +Some built-in package use-package declarations are missing =:ensure nil=: +- =selection-framework.el=: =delsel= (line 54) +- Several others throughout + +*Impact:* Minimal - use-package won't try to install built-ins anyway. But inconsistent with the pattern used elsewhere. + +*Fix:* Add =:ensure nil= for consistency, or document why some have it and others don't. + +** TODO [#C] Consider lazy-loading more packages :performance:startup: +:PROPERTIES: +:FILE: modules/selection-framework.el +:LINES: 22, 40, 48, 151, 166, 240-253 +:END: + +Several completion packages use =:demand t= (vertico, marginalia, orderless, prescient): +- Vertico: Reasonable to demand (core UI) +- Marginalia: Could be :after vertico +- Orderless: Could be :after vertico +- Prescient: Could be :after vertico +- Company-prescient: Could be :after (vertico company) + +*Impact:* All load at startup, adds ~100ms. Not critical, but could be optimized. + +*Fix:* Profile with esup to see actual impact. If it's <100ms, probably not worth the complexity. + +** TODO [#C] Add validation for chime.el local path :stability:enhancement: +:PROPERTIES: +:FILE: modules/org-agenda-config.el +:LINE: 264 +:END: + +Config loads chime from local directory =~/code/chime.el= without checking if it exists. + +*Impact:* If directory doesn't exist, load fails silently or with cryptic error. + +*Fix:* Add existence check with helpful error message: +#+begin_src elisp +:load-path (lambda () + (let ((path "~/code/chime.el")) + (if (file-directory-p path) + path + (warn "chime.el not found at %s" path) + nil))) +#+end_src + +** TODO [#C] Document why org-msg uses local fork :documentation:maintenance: +:PROPERTIES: +:FILE: modules/mail-config.el +:LINE: 287 +:END: + +Loading org-msg from local path =/home/cjennings/code/org-msg= instead of MELPA. + +*Question:* Is this a temporary fork with patches? Does it need to stay local? + +*Fix:* Add comment explaining: +- What changes are in local fork +- Whether it's temporary or permanent +- Link to upstream PR if patches are submitted +- When it can switch back to MELPA + +** TODO [#C] Performance: Company idle-delay is very high :performance:usability: +:PROPERTIES: +:FILE: modules/selection-framework.el +:LINE: 212 +:END: + +Company idle-delay is set to 2 seconds, which is quite slow. Modern editors typically use 0.1-0.3s. + +*Impact:* Completion feels sluggish, requires manual triggering often. + +*Recommendation:* +- If keeping Company: Try 0.3 seconds +- If switching to Corfu: Default 0.1s is perfect + +User preference, but current setting feels unresponsive. + +** TODO [#C] org-protocol may not be fully configured :functionality:enhancement: +:PROPERTIES: +:FILE: modules/org-config.el +:LINES: 94-95, 116 +:END: + +=org-protocol= is loaded (line 95) and added to org-modules (line 116), but: +- No desktop entry file mentioned +- No documentation on how to use it +- org-webclipper exists but unclear if it uses org-protocol + +*Fix:* Either: +1. Document org-protocol setup (desktop file, browser integration) +2. Remove if unused (org-webclipper might be the preferred approach) + +** TODO [#D] Consider adding use-package :diminish for minor modes :enhancement:ui: +:PROPERTIES: +:FILE: Multiple modules +:END: + +Many minor modes appear in the modeline even though doom-modeline hides them. + +*Enhancement:* Add =:diminish= to use-package declarations for: +- =symbol-overlay-mode= +- =git-gutter-mode= +- =flycheck-mode= +- =yas-minor-mode= +- =ws-butler-mode= +- =rainbow-mode= + +Cleaner modeline if doom-modeline isn't used or fails to load. + +** TODO [#D] Add .dir-locals.el for project-specific settings :enhancement:devex: +:PROPERTIES: +:FILE: N/A (new file) +:END: + +Create =.dir-locals.el= in =~/.emacs.d= to: +- Set =fill-column= to 80 for elisp files +- Enable =flycheck-mode= for all elisp +- Set =checkdoc= settings locally +- Configure =outline-minor-mode= for easy navigation + +Helps maintain consistency when editing config. + +** TODO [#D] Consider moving from doom-modeline to mood-line :enhancement:performance: +:PROPERTIES: +:FILE: modules/modeline-config.el +:END: + +Doom-modeline is feature-rich but heavy. For the minimal info you're displaying, mood-line might be better: + +*Mood-line advantages:* +- ~10x faster than doom-modeline +- Pure elisp (no external dependencies) +- Very simple, hackable codebase +- Shows exactly what you need: filename, position, major-mode +- No nerd-icons dependency (can still use them if wanted) + +*Doom-modeline advantages:* +- More battle-tested +- Better git integration +- More features (even if disabled) + +*Recommendation:* Try mood-line. If you miss doom-modeline features, easy to switch back. Performance difference is noticeable on older hardware. + +** TODO [#D] Add commentary headers to test utility files :documentation:testing: +:PROPERTIES: +:FILES: tests/testutil-general.el, tests/testutil-filesystem.el +:END: + +Test utility files should have Commentary sections explaining: +- What utilities are provided +- When to use each utility +- Examples of usage +- Relationship to quality-engineer.org guidelines + +Helps future test authors understand available infrastructure. + +** TODO [#D] keybindings.el trains user away from C-x u :ux:philosophy: +:PROPERTIES: +:FILE: modules/keybindings.el +:LINES: 126-130 +:END: + +The rebinding of =C-x u= to a message telling users to use =C-/= instead is... philosophically interesting. + +*Discussion points:* +- Enforces good habits (C-/ is indeed faster) +- But violates principle of least surprise +- Could frustrate users who know Emacs bindings +- Muscle memory is hard to retrain + +*Alternative:* Just leave =C-x u= working. Add which-key hint that C-/ is faster. + +** TODO [#D] Missing which-key labels for some custom keymaps :usability:discoverability: +:PROPERTIES: +:FILES: Multiple modules +:END: + +Some custom keymaps lack which-key descriptions: +- =cj/vc-map= is well documented (vc-config.el) +- =cj/jump-map= is well documented (keybindings.el) +- =cj/org-table-map= is well documented (org-config.el) + +But check all custom keymaps for completeness. Run: +#+begin_src elisp +(apropos-variable "^cj/.*-map$") +#+end_src + +And verify each has which-key labels. + +** TODO [#D] early-init.el could benefit from more section comments :documentation:maintainability: +:PROPERTIES: +:FILE: early-init.el +:END: + +File has good top-level commentary but individual sections could use more context: +- Why network check exists (explain offline package strategy) +- Why GC threshold is increased (explain impact) +- Benchmark-init section is good, replicate that style + +Makes it easier for others (or future you) to understand decisions. + +** TODO [#D] Consider adding persistent-scratch package :enhancement:usability: +:PROPERTIES: +:FILE: N/A +:END: + +The *scratch* buffer is very useful but loses content on restart. + +*Enhancement:* Add =persistent-scratch= package to: +- Auto-save scratch buffer contents +- Restore on startup +- Optionally persist multiple scratch buffers + +Useful for quick notes, code experiments, calculations that span sessions. + +* Priority Explanation + +** Priority A (Critical) +Issues that: +- Prevent functionality from working +- Cause errors or crashes +- Block startup or major features +- Have security implications +- Significantly impact performance (>1s delay) + +** Priority B (High) +Issues that: +- Affect architecture or maintainability significantly +- Better alternative packages exist +- Moderate performance impact (>100ms) +- Testing gaps in critical code +- Risk of future breakage + +** Priority C (Medium) +Issues that: +- Affect code quality or consistency +- Minor refactoring opportunities +- Documentation improvements +- Small usability enhancements +- Package optimization opportunities + +** Priority D (Low) +Issues that: +- Nice-to-have features +- Polish and refinement +- Alternative approaches to consider +- Documentation expansion +- Style/convention improvements + +* Package Recommendations Summary + +** Recommended Changes +1. *Company → Corfu*: Better performance, more modern, better maintained +2. *Consider mood-line over doom-modeline*: Much faster for minimal info needs +3. *Add Cape*: Modern completion-at-point backends (if switching to Corfu) +4. *Consider persistent-scratch*: QOL improvement for scratch buffer + +** Packages to Keep +- Vertico: Excellent choice, fast, well-maintained +- Consult: Perfect companion to Vertico +- Orderless: Best completion style available +- Embark: Powerful, could be used more extensively +- Marginalia: Great for annotations +- Magit: Industry standard, no alternatives +- Org-roam: Best Zettelkasten for Emacs +- Which-key: Essential for discoverability + +** Packages to Evaluate +- Dirvish: Heavy package. Consider if dired + nerd-icons + embark is sufficient +- Doom-modeline: Feature-rich but heavy. Mood-line is lighter alternative +- Projectile vs project.el: You're using Projectile. Project.el is built-in and lighter, but Projectile is more mature. Keep unless performance is an issue. + +* Testing Recommendations + +Based on your quality-engineer.org guidelines and existing test coverage: + +** Well-Tested Areas ✓ +- All custom-* utility functions (excellent coverage) +- undead-buffers (comprehensive tests) +- org-roam helpers (good coverage) +- keyboard-macros +- Test utilities themselves + +** Priority Testing Gaps + +*** High Priority +1. *org-agenda-config.el filtering functions* + - =cj/org-skip-subtree-if-habit= + - =cj/org-skip-subtree-if-not-overdue= (date-sensitive!) + - =cj/build-org-agenda-list= (file discovery) + +2. *custom-buffer-file.el interactive functions* + - Split =cj/move-buffer-and-file= into =cj/--move-buffer-and-file= (testable core) and interactive wrapper + - Same for =cj/rename-buffer-and-file= + - Same for =cj/delete-buffer-and-file= + +*** Medium Priority +3. *org-roam-config.el integration test* + - =cj/move-org-branch-to-roam= workflow test + - Test actual file creation and org-roam db update + +4. *path-utils consolidation* (after creating module) + - Test project-relative, home-relative, absolute path logic + - Test with symlinks, non-existent paths, permission errors + +5. *ai-config.el GPTel context management* + - =cj/gptel-add-file= with various file types + - =cj/gptel--fresh-org-prefix= timestamp formatting + +*** Lower Priority +6. *mail-config.el address completion* +7. *Browser/external open logic* +8. *Theme persistence functions* + +** Testing Patterns to Follow + +Your existing tests follow excellent patterns from quality-engineer.org: +- One file per function for unit tests +- Clear normal/boundary/error case organization +- Good use of test utilities (testutil-general, testutil-filesystem) +- Proper setup/teardown +- Descriptive test names + +*Keep this pattern!* It's working well for you. + +** Test-Driven Refactoring Opportunities + +When fixing Priority A-B issues, write tests first: +1. Test for the bug/missing function +2. See it fail +3. Fix the code +4. See it pass +5. Refactor with confidence + +This is especially important for: +- The missing =cj/goto-git-gutter-diff-hunks= function +- The duplicate =cj/network-available= variable +- Network check refactoring (mock the network!) + +* Architecture Observations + +** What You're Doing Right ✓ + +1. *Excellent module organization*: Clean separation of concerns +2. *Good use of user-constants.el*: Centralized configuration +3. *Comprehensive custom utilities*: Well-tested, reusable functions +4. *Modern completion framework*: Vertico/Consult/Embark stack is excellent +5. *Debug infrastructure pattern*: org-agenda-config-debug.el is a good model +6. *Test coverage philosophy*: Following your own guidelines well +7. *Early-init optimization*: Good understanding of startup optimization +8. *Custom keymap prefix*: C-; is a good choice, well-organized + +** Architectural Patterns to Consider + +1. *Consolidate common patterns*: + - Path handling → path-utils.el + - Debug logging → debug-logging.el + - File validation → file-utils.el + +2. *Reduce coupling*: + - Some modules depend on specific implementations (e.g., projectile vs project.el) + - Consider adapter pattern for switching between implementations + +3. *Error handling strategy*: + - Add condition-case wrappers around file operations + - Log errors consistently to *Messages* or debug buffer + - Fail gracefully (warn user but don't break session) + +4. *Configuration validation*: + - Add startup checks for critical paths/files + - Warn about missing optional dependencies + - Provide helpful error messages with solutions + +** Code Smells Observed + +1. *String concatenation for paths*: Use =expand-file-name= consistently +2. *Silent failures*: Some functions fail without user feedback +3. *Synchronous network operations*: Blocks startup unnecessarily +4. *Duplicate logic*: Path handling, project root detection +5. *Large functions*: Some functions >50 lines, should be split +6. *Global state*: Some functions modify global variables without clear ownership + +* Next Steps Recommendation + +** Week 1: Fix Critical Bugs (Priority A) +1. Fix duplicate =cj/network-available= declaration +2. Implement missing =cj/goto-git-gutter-diff-hunks= +3. Define =cj/log-silently= or remove usage +4. Fix network check blocking (biggest impact) + +** Week 2: Architectural Improvements (Priority B) +1. Evaluate Company vs Corfu (try Corfu for a week) +2. Consolidate debug logging +3. Create path-utils.el module +4. Add error handling to org-agenda rebuild + +** Week 3: Testing (Priority B) +1. Add tests for org-agenda filtering functions +2. Split interactive/non-interactive in custom-buffer-file +3. Add integration test for org-roam branch extraction + +** Week 4: Polish (Priority C-D) +1. Consolidate coding system setup +2. Improve documentation +3. Add which-key labels where missing +4. Clean up minor issues + +** Ongoing +- Add tests for any new functionality +- Profile startup time with esup periodically +- Review package updates for breaking changes +- Keep org-gcal, chime.el forks in sync with upstream + +* Questions for You + +1. *Company vs Corfu*: Do you have strong feelings about Company? Willing to try Corfu? + Answer: I'd be excited to try Corfu. I don't know how I'd configure it yet and it seems like a big change. However, I planned to move to Corfu sometime soon. + +2. *Network check*: Do you actually need to support offline operation, or can we simplify this? + Answer: We can simplify. There was a time when I was traveling a lot and didn't have network access. The current offline operation seemed to help startup performance. The sooner we realized we were offline, the sooner I'd have a working Emacs. Now, I don't think it provides much benefit. + +3. *Local forks*: Are chime.el and org-msg local forks temporary? When can they move to MELPA? + Answer: These are packages I currently either maintain or are in the process of creating. I need the local-paths set so I can test. If you have better ideas on how I can switch them from using a local package to using the stable version using vc-install, I'd be grateful. + +4. *Doom-modeline*: Are you using features beyond what I saw in config? Would mood-line be sufficient? + No, I'm not. Mood-line would be welcomed. + +5. *Testing coverage*: What modules do you most want tests for? Anything you're nervous about breaking? + I'll probably look for large methods with lots of LOC and multiple tasks, then break them up for better testability. I was hoping you would point those out for me so I could focus on them. Will you? + +6. *Performance*: Any particular operations feel slow? (Agenda rebuild? Mail sync? Completion?) + Org Agenda is problematic and slow. I could get some insights into how to optimize it if it were well tested. + + +Other than that, here's my roadmap for fixing/improving +- video/audio config could use some testing around which sinks to attach to. It doesn't matter to me that this is Linux centric since it's my config. +- I'm not sure the UX in flyspell and abbrev is right. It could use some more attention. +- Same with Elfeed. While I had Elfeed dashboard at some point, it doesn't bring any joy to see a mostly blank screen when I check Elfeed. +- DWIM shell commands is alright. I wonder if I can leverage them better into eshell. +- calibredb is slow, but that's the package working on 14k+ pdfs and epubs. The right thing to do is to shrink the ebook inventory to < 1k or so books. +- I was thinking of investigating bettter diffs with difftastic. If it's straightforward and simple, I should jump at it. +- I would like to implement code-maat and code-compass within Emacs +- It would be good to have a solid profiler workflow so I can see what's going on inside my own methods and packages. For instance, I don't have the tools to tell me why it takes so long to generate my daily agenda. There's little observability. +- I absolutely need a workflow so I can go from org-mode file to reveal.js presentation using httpd server in Emacs with the press of a button. I know it can be done. Export the org file with injected css into the httpd directory, start the httpd server, then open a browser fullscreen on the file. That's pretty much 90% of the work right there. +- If I could figure out the latex-config so that I could author something non-trivial, I'd be happy. Right now, it's a bunch of cut/paste snippets from everyone else's config and it doesn't work. +- mail-config: the whole attachments workflow is awkward, but so necessary for daily life. It really needs improvement. +- then there's the whole org-contacts issue working with chime.el and birthdays. sexp expressions for dates? I should either figure them out and support them in chime, or I should disable them and find another way. +- it would be good to work with llms the way I do with claude code. gptel feels like a step in that direction and you can switch backends besides. but I need to either build a bunch of tools or install an MCP server. Which way to go? +- I would like to extract the code in local-repository that creates the repo so I can unit test the hell out of it and use it as a library for my own local repo. Seems like there's too much extraneous functionality there. +- lorem seems to have an error pop up each session about the markhov chain resetting. either that's bad and should be fixed or it's not bad and lorem should stfu. +- I believe jumper should probably be my next package, but I haven't had the time to spend on it. + +* Final Thoughts + +Your config is **quite good overall**: +- Well-organized modular structure +- Excellent test coverage for utilities +- Modern package choices (mostly) +- Good documentation and comments +- Following elisp idioms reasonably well + +The critical issues (Priority A) are straightforward fixes. The architectural suggestions (Priority B) are about making the codebase more maintainable long-term. Everything else is refinement. + +Focus on: +1. Fix the bugs that break functionality +2. Consider Corfu migration (biggest ROI for effort) +3. Add tests for date-sensitive agenda logic +4. Everything else is gravy + +You're clearly thoughtful about your config and willing to refactor when needed. These issues are normal for a mature, actively-used configuration. Keep up the good work! + +* Second Opinion: Ruthless Prioritization & Reality Checks +:PROPERTIES: +:DATE: 2025-10-30 +:END: + +After reviewing your answers and additional roadmap items, here's honest feedback on what matters, what doesn't, and what you should actually do. + +** Key Insights from Your Answers + +*** Company → Corfu Migration: GREEN LIGHT +You're excited, you were planning it anyway. Corfu configuration is actually *simpler* than Company, not harder. This is a quick win with immediate UX improvement. + +*Reality:* 2 hours of work, noticeable performance improvement. Do it this weekend. + +*** Network Check: DELETE IT IMMEDIATELY +You confirmed it's technical debt from when you traveled. It's adding 1+ seconds to every startup for a problem you no longer have. + +*Reality:* 15 minutes to delete ~100 lines of code. Instant gratification. Do this first. + +*** Local Package Development Workflow: NEEDS PATTERN +You maintain chime.el and org-msg locally for testing. Current approach works but isn't elegant. See implementation pattern below. + +*** Mood-line Switch: EASY WIN +You don't need doom-modeline features. Mood-line is 10x faster and simpler. + +*Reality:* 30 minutes. Do it. + +*** Large Functions to Break Up: MOSTLY FINE +Analyzed your codebase. Most functions are reasonably sized. The ones you mentioned: +- =dirvish-config.el:350-406= =cj/dired-copy-path-as-kill= (57 lines) - Could split, but works fine +- =org-roam-config.el:250-298= =cj/move-org-branch-to-roam= (49 lines) - Actually well-designed with helpers +- =org-agenda-config.el:91-105= =cj/build-org-agenda-list= (15 lines) - Small but THIS IS YOUR PERFORMANCE BOTTLENECK + +*Reality:* Your code organization is fine. Your problem is *performance observability*, not function length. + +*** Org Agenda Performance: ROOT CAUSE IDENTIFIED +This is your actual pain point. But you're flying blind without profiling infrastructure. + +*Hypothesis:* =cj/build-org-agenda-list= recursively scans entire projects directory on every agenda open with: +- No caching (even when files unchanged) +- No error handling +- Synchronous file I/O blocking UI +- Probably hundreds of file-exists-p calls + +*Reality:* You need profiling tools FIRST, then optimization. Don't guess, measure. + +** TIER 1: Do These First (High Impact, Low Effort) +*Time investment: One weekend* +*Status: START HERE* + +*** TODO [#A] Remove network check entirely :performance:critical: +:PROPERTIES: +:FILE: early-init.el +:LINES: 76-78, 104-105, 189, 206 +:EFFORT: 15 minutes +:IMPACT: Removes 1+ seconds from every startup +:END: + +Delete the following: +1. =cj/network-available= variable declarations (both) +2. =cj/internet-up-p= function and all calls +3. =cj/use-online-repos= flag logic +4. Any package.el conditionals based on network status + +Let package.el handle its own errors gracefully. Modern Emacs does this fine. + +*** TODO [#A] Fix missing cj/log-silently definition :bug:critical: +:PROPERTIES: +:FILE: modules/wrap-up.el +:LINE: 28 +:EFFORT: 5 minutes +:END: + +Either: +1. Move =cj/log-silently= from =org-agenda-config-debug.el= to =config-utilities.el= (load early) +2. Or replace with simple =(message ...)= call + +The function is only used in one place, so simple message might be sufficient. + +*** TODO [#A] Remove duplicate cj/network-available declaration :bug:critical: +:PROPERTIES: +:FILE: early-init.el +:LINES: 104-105 +:EFFORT: 2 minutes +:END: + +Delete the duplicate at lines 104-105. Keep only the first declaration at line 76. + +*Note:* This becomes moot if you delete network check entirely (recommended). + +*** TODO [#A] Fix missing cj/goto-git-gutter-diff-hunks function :bug:critical: +:PROPERTIES: +:FILE: modules/vc-config.el +:LINE: 123 +:EFFORT: 15 minutes +:END: + +Keybinding =C-; v d= references undefined function. + +Implement as: +#+begin_src elisp +(defun cj/goto-git-gutter-diff-hunks () + "Jump to git-gutter diff hunks using consult." + (interactive) + (require 'git-gutter) + (consult-line "^[+\\-]")) ;; Or use git-gutter:popup-hunk +#+end_src + +Or remove the keybinding if not needed. + +*** TODO [#B] Migrate Company to Corfu :enhancement:performance: +:PROPERTIES: +:FILE: modules/selection-framework.el +:LINES: 202-236 +:EFFORT: 2 hours +:IMPACT: 3x faster completion, simpler config +:END: + +*Why Corfu:* +- ~3x faster (child frames vs overlays) +- Better maintained +- Simpler codebase (~500 LOC vs ~3000 LOC) +- Works seamlessly with Vertico/Consult +- Better integration with Cape for backends + +*Migration:* +#+begin_src elisp +(use-package corfu + :ensure t + :demand t + :bind (:map corfu-map + ("TAB" . corfu-next) + ("S-TAB" . corfu-previous)) + :custom + (corfu-auto t) + (corfu-auto-delay 0.1) ;; Much faster than your 2s company delay! + (corfu-auto-prefix 2) + (corfu-quit-no-match 'separator) + :init + (global-corfu-mode)) + +(use-package corfu-popupinfo + :after corfu + :hook (corfu-mode . corfu-popupinfo-mode) + :custom + (corfu-popupinfo-delay '(0.5 . 0.2))) + +(use-package cape + :ensure t + :after corfu + :init + (add-to-list 'completion-at-point-functions #'cape-dabbrev) + (add-to-list 'completion-at-point-functions #'cape-file) + (add-to-list 'completion-at-point-functions #'cape-keyword)) +#+end_src + +Remove entire company configuration. Keep mu4e completion settings (Corfu respects them). + +*Configuration is actually simpler than Company.* Just do it. + +*** TODO [#B] Switch doom-modeline to mood-line :enhancement:performance: +:PROPERTIES: +:FILE: modules/modeline-config.el +:EFFORT: 30 minutes +:IMPACT: 10x faster modeline updates +:END: + +Replace doom-modeline config with: +#+begin_src elisp +(use-package mood-line + :ensure t + :demand t + :config + (mood-line-mode)) +#+end_src + +That's it. Mood-line shows: buffer name, position, major-mode, vc status. Pure elisp, very fast. + +If you miss doom-modeline features, easy to switch back. But try mood-line for a week. + +*** TODO [#C] Fix lorem markov chain error :bug:minor: +:PROPERTIES: +:FILE: modules/lorem-config.el (or wherever lorem is configured) +:EFFORT: 5 minutes +:END: + +The error message is probably harmless initialization noise. Either: +1. Wrap lorem initialization in =(with-demoted-errors ...)= +2. Configure lorem to suppress the warning +3. Disable lorem if you don't use it + +Check your config for lorem setup and add error suppression. + +** TIER 2: Build Observability Infrastructure (HIGHEST VALUE) +*Time investment: One week* +*Status: CRITICAL DEPENDENCY FOR EVERYTHING ELSE* + +*** TODO [#A] Create debug-profiling.el module :infrastructure:performance: +:PROPERTIES: +:FILE: modules/debug-profiling.el (new file) +:EFFORT: 3-4 hours +:IMPACT: Unlocks all performance optimization work +:END: + +This is your #1 blocker for fixing org-agenda and other performance issues. + +Create comprehensive profiling infrastructure: + +#+begin_src elisp +;;; debug-profiling.el --- Profiling and performance debugging tools -*- lexical-binding: t; -*- + +;;; Commentary: +;; Unified profiling infrastructure for measuring and optimizing performance. +;; Provides helpers for: +;; - Function timing (individual and batch) +;; - Memory profiling +;; - Startup profiling +;; - Interactive profiling sessions +;; +;; Usage: +;; M-x cj/profile-function RET cj/build-org-agenda-list RET +;; M-x cj/profile-startup +;; (cj/time-it "agenda rebuild" (cj/build-org-agenda-list)) + +;;; Code: + +(require 'profiler) +(require 'benchmark) + +(defvar cj/profiling-log-buffer "*CJ Profile Log*" + "Buffer name for profiling results.") + +(defvar cj/profiling-enabled nil + "When non-nil, enable automatic timing of instrumented functions.") + +(defun cj/time-it (description &rest body) + "Execute BODY and log timing with DESCRIPTION." + (let* ((start-time (current-time)) + (result (car body)) + (elapsed (float-time (time-subtract (current-time) start-time)))) + (with-current-buffer (get-buffer-create cj/profiling-log-buffer) + (goto-char (point-max)) + (insert (format "[%s] %s: %.3f sec\n" + (format-time-string "%H:%M:%S") + description + elapsed))) + (message "%s: %.3f sec" description elapsed) + result)) + +(defmacro cj/measure (&rest body) + "Measure execution time of BODY, return result and timing." + `(let ((start-time (current-time)) + (result (progn ,@body)) + (end-time (current-time))) + (cons result (float-time (time-subtract end-time start-time))))) + +(defun cj/profile-function (function &optional runs) + "Profile FUNCTION by calling it RUNS times (default 1). +Shows results in dedicated buffer with call tree." + (interactive + (list (intern (completing-read "Function to profile: " obarray 'fboundp t)) + (when current-prefix-arg + (read-number "Number of runs: " 10)))) + (setq runs (or runs 1)) + (profiler-start 'cpu) + (dotimes (_ runs) + (funcall function)) + (profiler-stop) + (profiler-report) + (message "Profiled %s (%d run%s)" function runs (if (> runs 1) "s" ""))) + +(defun cj/profile-startup () + "Profile Emacs startup by restarting with profiler enabled. +Results are saved to profile.el in user-emacs-directory." + (interactive) + (let ((profile-file (expand-file-name "startup-profile.el" user-emacs-directory))) + (profiler-start 'cpu+mem) + (message "Restart Emacs to profile startup. Results will be in %s" profile-file) + (add-hook 'emacs-startup-hook + (lambda () + (profiler-report) + (profiler-report-write-profile profile-file) + (profiler-stop) + (message "Startup profiling complete. See %s" profile-file))))) + +(defun cj/benchmark-function (function &optional iterations) + "Benchmark FUNCTION over ITERATIONS (default 100). +Shows average, min, max, and total time." + (interactive + (list (intern (completing-read "Function to benchmark: " obarray 'fboundp t)) + (read-number "Iterations: " 100))) + (setq iterations (or iterations 100)) + (let ((times '())) + (dotimes (_ iterations) + (let* ((result (cj/measure (funcall function))) + (elapsed (cdr result))) + (push elapsed times))) + (let* ((total (apply #'+ times)) + (avg (/ total iterations)) + (min-time (apply #'min times)) + (max-time (apply #'max times))) + (message "%s (%d iterations): avg=%.4fs min=%.4fs max=%.4fs total=%.2fs" + function iterations avg min-time max-time total)))) + +(defun cj/instrument-package (package) + "Instrument all functions in PACKAGE for profiling with elp." + (interactive + (list (intern (completing-read "Package to instrument: " obarray)))) + (elp-instrument-package (symbol-name package)) + (message "Instrumented package: %s. Run M-x elp-results to see data." package)) + +(defun cj/profile-agenda-rebuild () + "Profile org-agenda rebuild with detailed timing." + (interactive) + (require 'org-agenda) + (cj/time-it "Full agenda rebuild" (cj/build-org-agenda-list))) + +(defun cj/show-profile-log () + "Display the profiling log buffer." + (interactive) + (display-buffer (get-buffer-create cj/profiling-log-buffer))) + +(defun cj/clear-profile-log () + "Clear the profiling log buffer." + (interactive) + (with-current-buffer (get-buffer-create cj/profiling-log-buffer) + (erase-buffer))) + +;; Keybindings (add to your keybindings.el) +;; (global-set-key (kbd "C-; p f") #'cj/profile-function) +;; (global-set-key (kbd "C-; p b") #'cj/benchmark-function) +;; (global-set-key (kbd "C-; p l") #'cj/show-profile-log) +;; (global-set-key (kbd "C-; p a") #'cj/profile-agenda-rebuild) + +(provide 'debug-profiling) +;;; debug-profiling.el ends here +#+end_src + +Load this early in init.el: +#+begin_src elisp +(when (or (eq cj/debug-modules t) + (memq 'profiling cj/debug-modules)) + (require 'debug-profiling (expand-file-name "modules/debug-profiling" user-emacs-directory))) +#+end_src + +*** TODO [#A] Profile org-agenda-rebuild to find bottleneck :performance:critical: +:PROPERTIES: +:FILE: modules/org-agenda-config.el +:EFFORT: 1 hour +:DEPENDS: debug-profiling.el +:END: + +Once profiling infrastructure exists: + +1. Run: =M-x cj/profile-function RET cj/build-org-agenda-list RET= +2. Run: =M-x cj/benchmark-function RET cj/build-org-agenda-list RET 10= +3. Instrument org-agenda package: =M-x cj/instrument-package RET org-agenda RET= +4. Review results with =M-x elp-results= + +*Hypothesis to test:* +- Is time spent in file I/O (directory-files-recursively)? +- Is it parsing org files? +- Is it just too many files? +- Is there a slow helper function being called repeatedly? + +*Expected findings:* +- Probably 80%+ time in =cj/add-files-to-org-agenda-files-list= +- Likely no caching, runs every time +- Possible N+1 file access pattern + +*Next steps after profiling:* +- Add file-notify watchers to invalidate cache only when projects-dir changes +- Cache the file list +- Run rebuild async on startup + +*** TODO [#B] Add instrumentation to cj/build-org-agenda-list :performance:observability: +:PROPERTIES: +:FILE: modules/org-agenda-config.el +:EFFORT: 30 minutes +:DEPENDS: debug-profiling.el, profiling results +:END: + +After profiling identifies bottleneck, add instrumentation: + +#+begin_src elisp +(defun cj/build-org-agenda-list () + "Rebuilds the org agenda list with instrumentation." + (interactive) + (let ((start-time (current-time))) + ;; reset org-agenda-files + (setq org-agenda-files (list inbox-file schedule-file gcal-file)) + + ;; Time the expensive operation + (let ((scan-start (current-time))) + (cj/add-files-to-org-agenda-files-list projects-dir) + (message "Scanned projects-dir in %.3f sec" + (float-time (time-subtract (current-time) scan-start)))) + + (let ((total-time (float-time (time-subtract (current-time) start-time)))) + (message "Rebuilt org-agenda-files in %.3f sec (%d files)" + total-time + (length org-agenda-files))))) +#+end_src + +This gives you observability on every agenda rebuild. + +*** TODO [#B] Add caching to org-agenda rebuild :performance:critical: +:PROPERTIES: +:FILE: modules/org-agenda-config.el +:EFFORT: 2 hours +:DEPENDS: Profiling results +:END: + +*Only do this after profiling confirms file scanning is the bottleneck.* + +Implement caching with file-notify: + +#+begin_src elisp +(defvar cj/org-agenda-cache nil + "Cached list of org-agenda files.") + +(defvar cj/org-agenda-cache-dirty t + "When non-nil, agenda cache needs rebuilding.") + +(defun cj/invalidate-agenda-cache (&rest _) + "Mark agenda cache as dirty." + (setq cj/org-agenda-cache-dirty t)) + +(defun cj/build-org-agenda-list-cached () + "Build org-agenda list with caching." + (interactive) + (when (or (not cj/org-agenda-cache) + cj/org-agenda-cache-dirty) + (let ((start-time (current-time))) + (setq cj/org-agenda-cache (list inbox-file schedule-file gcal-file)) + (cj/add-files-to-org-agenda-files-list projects-dir) + (setq cj/org-agenda-cache org-agenda-files) + (setq cj/org-agenda-cache-dirty nil) + (message "Rebuilt agenda cache in %.3f sec (%d files)" + (float-time (time-subtract (current-time) start-time)) + (length cj/org-agenda-cache)))) + (setq org-agenda-files cj/org-agenda-cache)) + +;; Set up file watching +(require 'filenotify) +(file-notify-add-watch projects-dir + '(change) + #'cj/invalidate-agenda-cache) +#+end_src + +*** TODO [#B] Test org-agenda filtering functions :testing:critical: +:PROPERTIES: +:FILE: tests/org-agenda-config-test.el (new file) +:EFFORT: 2-3 hours +:END: + +These functions are date-sensitive and break silently. High-value tests: + +#+begin_src elisp +;;; org-agenda-config-test.el --- Tests for org-agenda-config -*- lexical-binding: t; -*- + +(require 'ert) +(require 'org-agenda-config) + +(ert-deftest test-cj/org-skip-subtree-if-habit () + "Test habit filtering." + (with-temp-buffer + (org-mode) + (insert "* TODO Test\n:PROPERTIES:\n:STYLE: habit\n:END:\n") + (goto-char (point-min)) + (should (cj/org-skip-subtree-if-habit)))) + +(ert-deftest test-cj/org-skip-subtree-if-not-overdue () + "Test overdue task detection." + (with-temp-buffer + (org-mode) + ;; Task scheduled yesterday (overdue) + (insert "* TODO Overdue\nSCHEDULED: <2025-10-29>\n") + (goto-char (point-min)) + (should-not (cj/org-skip-subtree-if-not-overdue)) + + ;; Task scheduled tomorrow (not overdue) + (erase-buffer) + (insert "* TODO Future\nSCHEDULED: <2025-10-31>\n") + (goto-char (point-min)) + (should (cj/org-skip-subtree-if-not-overdue)))) +#+end_src + +** TIER 3: Quick Wins (After Tier 1 & 2) +*Time investment: 1-2 hours each* +*Status: Only tackle after profiling infrastructure is done* + +*** TODO [#B] Implement org-to-reveal.js workflow :enhancement:usability: +:PROPERTIES: +:FILE: modules/org-config.el or new modules/org-present-config.el +:EFFORT: 2 hours +:IMPACT: Solves specific, concrete need +:END: + +You said: "I know it can be done. Export to reveal.js, start httpd, open browser." + +You're right, it's straightforward: + +#+begin_src elisp +(use-package ox-reveal + :ensure t + :after org + :custom + (org-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js")) + +(use-package simple-httpd + :ensure t + :custom + (httpd-port 8080) + (httpd-root "~/presentations")) + +(defun cj/org-present-reveal () + "Export current org file to reveal.js and present via httpd." + (interactive) + (unless (eq major-mode 'org-mode) + (user-error "Not in an org-mode buffer")) + + (let* ((httpd-dir (expand-file-name httpd-root)) + (output-file (expand-file-name + (concat (file-name-base) ".html") + httpd-dir))) + + ;; Ensure output directory exists + (make-directory httpd-dir t) + + ;; Export to reveal.js HTML + (org-reveal-export-to-html) + + ;; Move to httpd directory + (let ((exported-file (concat (file-name-base) ".html"))) + (rename-file exported-file output-file t)) + + ;; Start httpd if not running + (unless (process-status "httpd") + (httpd-start) + (message "Started httpd server on port %d" httpd-port)) + + ;; Open in browser (fullscreen) + (let ((url (format "http://localhost:%d/%s" + httpd-port + (file-name-nondirectory output-file)))) + (browse-url url) + (message "Presenting: %s" url)))) + +(with-eval-after-load 'org + (define-key org-mode-map (kbd "C-c C-v p") #'cj/org-present-reveal)) +#+end_src + +*That's it.* 30 lines. One keybinding. Done. + +Test with a simple org file: +#+begin_src org +,#+TITLE: Test Presentation +,#+REVEAL_THEME: moon + +,* Slide 1 +Content here + +,* Slide 2 +More content +#+end_src + +Press =C-c C-v p= and you're presenting. + +*** TODO [#B] Set up difftastic integration :enhancement:usability: +:PROPERTIES: +:FILE: modules/vc-config.el or modules/magit-config.el +:EFFORT: 30 minutes +:END: + +Install difftastic: =sudo pacman -S difftastic= or =cargo install difftastic= + +Then add to magit: + +#+begin_src elisp +(use-package magit-difftastic + :ensure t + :after magit + :bind (:map magit-status-mode-map + ("C-c d" . magit-difftastic-show)) + :custom + (magit-difftastic-executable "difft")) +#+end_src + +Or for native integration: +#+begin_src elisp +(setq magit-diff-refine-hunk 'all) ;; Already have this probably + +(defun cj/magit-difftastic-diff (args files) + "Show diff using difftastic." + (interactive (magit-diff-arguments)) + (require 'magit) + (let ((command (concat "difft " (mapconcat #'identity args " ")))) + (magit-git-command command))) + +(transient-append-suffix 'magit-diff '(-1 -1) + '("D" "Difftastic diff" cj/magit-difftastic-diff)) +#+end_src + +Simple and useful. Just do it. + +*** TODO [#C] Implement local package development workflow :enhancement:architecture: +:PROPERTIES: +:FILES: modules/org-agenda-config.el, modules/mail-config.el +:EFFORT: 1 hour +:END: + +You maintain chime.el and org-msg. You need to switch between local dev and stable versions easily. + +*Clean pattern:* + +In =user-constants.el=: +#+begin_src elisp +(defcustom cj/development-packages '() + "List of packages to load from local development paths. +When a package symbol is in this list, load from ~/code/<package>. +Otherwise use stable version via vc-install or MELPA. + +Example: (setq cj/development-packages '(chime org-msg))" + :type '(repeat symbol) + :group 'cj) + +(defun cj/use-local-package-p (package) + "Return non-nil if PACKAGE should be loaded from local path." + (memq package cj/development-packages)) +#+end_src + +In your package configs: +#+begin_src elisp +;; Chime configuration +(if (cj/use-local-package-p 'chime) + ;; Development mode: use local path + (use-package chime + :load-path "~/code/chime.el" + :demand t + ;; ... rest of config ... + ) + ;; Production mode: use stable version + (use-package chime + :vc (:url "https://github.com/yourusername/chime.el") + :demand t + ;; ... rest of config ... + )) +#+end_src + +To switch modes, just toggle the symbol in =cj/development-packages= and restart Emacs. + +*Benefits:* +- Clear intent: variable name says what it does +- Easy to toggle: add/remove symbols from list +- Version controlled: your config documents which packages you're actively developing +- No path duplication: define path logic once + +** TIER 4: Maybe/Someday (Proceed with Caution) +*Time investment: Unknown, possibly infinite* +*Status: Only do if you have concrete use case* + +*** HOLD [#D] Investigate code-maat/code-compass in Emacs :enhancement:tooling: +:PROPERTIES: +:REASON: Complexity vs value unclear +:END: + +*Hard truth:* This is a big project. Code-maat is a mature Java tool with significant functionality. + +*Questions before investing time:* +1. What would Emacs integration give you that CLI doesn't? +2. How often do you actually use code-maat? +3. Is this solving a real problem or is it intellectually interesting? + +*Recommendation:* Use the CLI tools. Call them from Emacs if needed: +#+begin_src elisp +(defun cj/code-maat-analyze (git-log-file) + "Run code-maat analysis on GIT-LOG-FILE." + (interactive "fGit log file: ") + (async-shell-command + (format "code-maat -l %s -c git2 -a coupling" git-log-file) + "*Code Maat Results*")) +#+end_src + +Don't reimplement it in elisp unless you have a very specific need the CLI can't meet. + +*** HOLD [#D] Fix LaTeX configuration :documentation:enhancement: +:PROPERTIES: +:REASON: No concrete use case yet +:END: + +You said: "Right now, it's a bunch of cut/paste snippets from everyone else's config and it doesn't work." + +*Hard truth:* LaTeX config is complex because LaTeX is complex. Don't invest time until you have a specific document you need to write. + +*When you do need it:* +1. Start with one concrete document (paper? letter? resume?) +2. Get that one document working +3. Extract the config that made it work +4. Then generalize + +*Don't* try to build a complete LaTeX environment speculatively. You'll waste time on edge cases you'll never hit. + +*Minimal starting point when you need it:* +#+begin_src elisp +(use-package auctex + :ensure t + :defer t + :mode ("\\.tex\\'" . LaTeX-mode) + :custom + (TeX-auto-save t) + (TeX-parse-self t) + (TeX-master nil)) +#+end_src + +That's it. Start there. Add more when you hit actual problems. + +*** HOLD [#D] Improve Elfeed dashboard UX :enhancement:ui: +:PROPERTIES: +:REASON: Need to clarify actual usage patterns +:END: + +You said: "it doesn't bring any joy to see a mostly blank screen when I check Elfeed." + +*Questions:* +1. Do you actually use RSS regularly, or is it aspirational? +2. If blank screen = no new items, is that a problem? +3. Would you use RSS more if the UX was better, or is RSS not part of your workflow? + +*Options:* +1. *If you don't use RSS:* Remove Elfeed. One less thing to maintain. +2. *If you want to use RSS more:* Start by curating better feeds, not fixing UI +3. *If blank screen bothers you:* Add a "no new items" message or show last N items regardless of read status + +Don't fix tooling for a workflow you're not sure you want. + +*** HOLD [#D] DWIM shell + eshell integration :enhancement:shell: +:PROPERTIES: +:REASON: Current solution works fine +:END: + +You have 815 lines of dwim-shell-config. It works. Leave it alone. + +*Hard truth:* This is a working system. "I wonder if I can leverage them better" is not a problem statement. + +Unless you have a specific workflow that's currently painful, don't touch this. + +*** HOLD [#D] Calibredb performance optimization :performance: +:PROPERTIES: +:REASON: Root cause is data volume, not code +:END: + +You correctly identified: "The right thing to do is to shrink the ebook inventory to < 1k or so books." + +*You already know the answer.* Don't optimize code when the problem is 14k+ files. + +Curate your library. Delete what you won't read. This is a data problem, not a code problem. + +*** HOLD [#D] Flyspell/abbrev UX improvements :enhancement:usability: +:PROPERTIES: +:REASON: Vague complaint, no specific pain points +:END: + +You said: "I'm not sure the UX is right. It could use some more attention." + +*This is not actionable.* Come back when you can say: +- "Pressing X does Y but I want Z" +- "It's too slow when..." +- "It conflicts with..." + +Until then, it's bikeshedding. + +*** HOLD [#D] Video/audio config sink testing :testing:enhancement: +:PROPERTIES: +:REASON: Nice to have, not blocking anything +:END: + +You said: "could use some testing around which sinks to attach to" + +*Questions:* +1. Does it currently work for your use case? +2. Do you switch audio sinks often? +3. Is this actually painful or just "would be nice"? + +If it works, leave it. If it doesn't work, describe the failure mode first. + +*** HOLD [#D] Build jumper package :project:packaging: +:PROPERTIES: +:REASON: Another package to maintain, unclear value +:END: + +You said: "I believe jumper should probably be my next package, but I haven't had the time." + +*Hard questions:* +1. What problem does jumper solve? +2. Do existing navigation packages (avy, ace-window, consult-line) not solve it? +3. Are you building this for yourself or for others? +4. How will you maintain it alongside chime and org-msg? + +If you're excited about it: Build it. But recognize it's a significant time investment. + +If you're not excited: Don't. You already maintain two packages. + +*** HOLD [#D] Extract local-repository creation logic :refactor:library: +:PROPERTIES: +:REASON: Unclear benefit +:END: + +You said: "extract the code... so I can unit test the hell out of it and use it as a library" + +*Questions:* +1. What would you use the library for beyond local-repository? +2. Is local-repository not working currently? +3. Are you planning to build other tools that need this? + +Don't extract libraries speculatively. Extract when you have two concrete use cases. + +*** HOLD [#D] Org-contacts + chime.el birthdays integration :enhancement:integration: +:PROPERTIES: +:REASON: Should be fixed in chime, not config +:END: + +You said: "I should either figure out sexp expressions and support them in chime, or disable them" + +*This is a chime.el issue, not a config issue.* + +File it as a chime.el feature request or bug. Your config shouldn't work around package limitations. + +** What NOT To Do + +*** DON'T: Optimize Before Profiling +You can't fix performance issues you can't measure. Build profiling infrastructure FIRST. + +*** DON'T: Build Speculative Libraries +Extract code into libraries when you have 2+ concrete use cases. Not before. + +*** DON'T: Fix Vague Complaints +"UX could be better" is not actionable. Come back with specific pain points. + +*** DON'T: Reimplement Mature CLI Tools +code-maat is Java. It works. Don't rewrite it in elisp. + +*** DON'T: Configure for Hypothetical Use Cases +LaTeX doesn't work? Come back when you need to write a specific LaTeX document. + +*** DON'T: Maintain More Packages Than You Can Support +You have chime and org-msg. That's plenty. Think hard before adding jumper. + +** Large Functions Analysis + +You asked me to identify large, complex functions that need breaking up. + +*Reality check:* Your functions are mostly fine. Here's what I found: + +*** Functions You Mentioned + +*1. dirvish-config.el:350-406 =cj/dired-copy-path-as-kill= (57 lines)* +- Has 6 responsibilities: validation, project detection, path formatting, org-link formatting, clipboard, feedback +- *Status:* Works fine, moderately complex +- *Recommendation:* Could extract helpers (=cj/--determine-path-type=, =cj/--format-path-for-display=), but not urgent +- *Priority:* [#C] - Refactor for testability when you have time + +*2. org-roam-config.el:250-298 =cj/move-org-branch-to-roam= (49 lines)* +- Already well-decomposed with helper functions! +- Uses =cj/org-link-get-description=, =cj/--generate-roam-slug=, =cj/--demote-org-subtree=, =cj/--format-roam-node= +- *Status:* Good design, clear logic flow +- *Recommendation:* Add integration test, but don't refactor further +- *Priority:* [#B] - Add tests, keep implementation + +*3. org-agenda-config.el:91-105 =cj/build-org-agenda-list= (15 lines)* +- Small function, but THIS IS YOUR PERFORMANCE BOTTLENECK +- Not because of size, but because it recursively scans directories without caching +- *Status:* CRITICAL ISSUE +- *Recommendation:* Profile it, add caching, add error handling +- *Priority:* [#A] - Profile and optimize ASAP + +*** Other Large Files + +*dwim-shell-config.el (815 lines)* +- Collection of DWIM commands +- *Status:* Works fine +- *Recommendation:* Leave it alone unless something breaks + +*custom-comments.el (636 lines)* +- Well-tested utility functions +- *Status:* No issues +- *Recommendation:* Keep as is + +*music-config.el (484 lines)* +- EMMS configuration +- *Recommendation:* Review when you mentioned video/audio sink testing + +*** The Real Issue + +Your problem isn't function length. Your problem is *performance observability*. + +You need: +1. Profiling infrastructure (debug-profiling.el) +2. Instrumentation in critical paths +3. Caching where appropriate +4. Error handling in file operations + +Focus on TIER 2 (observability infrastructure) before worrying about function decomposition. + +** Concrete Action Plan: This Weekend + +*** Saturday Morning (2-3 hours) + +1. *Delete network check* (15 min) + - Remove =cj/internet-up-p=, =cj/network-available=, all related code + - Test startup, should be 1+ seconds faster + +2. *Fix Priority A bugs* (45 min) + - Fix duplicate =cj/network-available= (if not deleted above) + - Implement =cj/goto-git-gutter-diff-hunks= or remove binding + - Fix =cj/log-silently= (move to config-utilities or use message) + +3. *Fix lorem error* (5 min) + - Find lorem config, suppress error message + +4. *Test everything still works* (15 min) + +*** Saturday Afternoon (2-3 hours) + +5. *Corfu migration* (2 hours) + - Remove company configuration + - Add corfu + corfu-popupinfo + cape + - Test completion in elisp, org, mu4e + - Verify mu4e still excludes completion + +6. *Switch to mood-line* (30 min) + - Remove doom-modeline + - Add mood-line configuration + - Restart, verify modeline works + +*** Sunday Morning (3-4 hours) + +7. *Create debug-profiling.el* (3 hours) + - Use the template I provided above + - Add to modules/ + - Configure in user-constants.el with =cj/debug-modules= + - Test basic commands work + +8. *Profile org-agenda* (30 min) + - Run =M-x cj/profile-agenda-rebuild= + - Run =M-x cj/profile-function RET cj/build-org-agenda-list= + - Document findings in *CJ Profile Log* + +9. *Write up findings* (30 min) + - What's slow? + - Why is it slow? + - What's the fix? + +*** Sunday Afternoon (Optional, 1-2 hours) + +10. *Reveal.js workflow* (2 hours) + - Implement =cj/org-present-reveal= + - Test with simple presentation + - Bind to key + +11. *Difftastic* (30 min) + - Install difftastic + - Configure magit integration + - Test on a real diff + +** Expected Outcomes + +After this weekend: +- ✅ Startup 1+ seconds faster (network check removed) +- ✅ No more broken keybindings or missing functions +- ✅ Completion is faster and more responsive (Corfu) +- ✅ Modeline updates are faster (mood-line) +- ✅ You have profiling infrastructure for all future optimization +- ✅ You understand why org-agenda is slow +- ✅ You have concrete data to guide optimization +- ✅ (Optional) You can present org files as reveal.js slides + +*** After This Weekend + +*Then stop and reassess.* + +- How do you feel about the changes? +- What's still bothering you? +- Is org-agenda faster after caching? (if you implement it) +- What's the next pain point? + +Don't commit to more work until you've lived with these changes for a week. + +** My Question for You + +Looking at your list of improvements, I see someone who: +- Likes building tools (jumper, code-maat integration, etc.) +- Gets excited by new technologies (difftastic, MCP, reveal.js) +- Has many "wouldn't it be cool if..." ideas + +But I also see someone who: +- Already has a working, sophisticated config +- Knows what's actually painful (org-agenda performance, mail attachments) +- Has limited time (maintaining chime, org-msg) + +*So here's my question:* + +*Are you building tools because they solve real problems, or because you enjoy building?* + +Both are valid answers! But the answer changes what you should prioritize: + +*If solving real problems:* +- Focus on TIER 1 & 2 (bugs, performance, observability) +- Ignore most of TIER 4 +- Build reveal.js workflow (concrete need) +- Fix mail attachments (daily pain) + +*If you enjoy building:* +- Pick ONE project (jumper? code-compass? profiling infrastructure?) +- Go deep on it +- Accept that other stuff will wait +- Be honest that it's for learning/fun, not necessity + +*My read:* You're mostly problem-solving, but you get distracted by shiny tools. + +*My advice:* Fix the pain points first (TIER 1 & 2). Then build one fun project. Then reassess. + +** gptel vs MCP: Specific Guidance + +You asked: "I need to either build a bunch of tools or install an MCP server. Which way to go?" + +*Answer: Build gptel functions. Here's why:* + +*** Why gptel + elisp Functions + +*Advantages:* +1. *Simpler:* Just elisp functions, no external server +2. *Integrated:* Native Emacs, shares your environment +3. *Debuggable:* Use edebug, step through code +4. *Maintainable:* You understand elisp, you wrote the config +5. *Flexible:* Can use any elisp API (org, dired, magit, etc.) +6. *Portable:* Works on any system with Emacs + gptel + +*What you can build:* +#+begin_src elisp +;; Example gptel tools +(defun cj/gptel-add-project-context () + "Add project README and key files to gptel context." + (interactive) + (let ((readme (expand-file-name "README.md" (project-root)))) + (when (file-exists-p readme) + (cj/gptel-add-file readme)))) + +(defun cj/gptel-analyze-function-at-point () + "Send function at point to LLM for analysis." + (interactive) + (let ((func (elisp--fnsym-in-current-sexp))) + (gptel-send (format "Analyze this function: %s" (symbol-function func))))) + +(defun cj/gptel-git-diff-review () + "Send current git diff to LLM for review." + (interactive) + (let ((diff (shell-command-to-string "git diff HEAD"))) + (gptel-send (concat "Review this diff:\n\n" diff)))) +#+end_src + +*This is much simpler than MCP and covers 90% of use cases.* + +*** When MCP Makes Sense + +*Only use MCP if:* +1. You want to share tools across multiple applications (VS Code + Emacs + CLI) +2. You need sandboxed execution for security +3. You're building reusable infrastructure for others +4. You want to use existing MCP servers someone else maintains + +*For Emacs-only workflows: Use gptel + elisp.* + +*** Recommended Approach + +1. Start with gptel + simple elisp functions +2. Build 3-5 useful commands (add-file, analyze-function, git-diff, org-context) +3. Use them for a month +4. If you find yourself wanting features MCP provides, reassess + +*Don't build MCP infrastructure speculatively.* Build it when gptel + elisp isn't enough. + +** Final Thoughts: Adjusted Priorities + +Your original document was thorough and well-analyzed. My additions: + +1. *Ruthless prioritization* - 4 tiers instead of flat list +2. *Observability first* - Can't optimize what you can't measure +3. *Reality checks* - Some "nice to haves" are rabbit holes +4. *Concrete implementations* - Not just "do this" but "here's the code" +5. *Hard questions* - Before building, ask "why?" and "for whom?" + +*Your config is good.* The issues are normal for a mature system. + +*Focus on:* +1. Fix the bugs (TIER 1) +2. Build profiling infrastructure (TIER 2) +3. Pick ONE fun project (reveal.js or difftastic) +4. Ignore everything else for now + +*Then live with it for a month* and see what still bothers you. + +You're thoughtful, skilled, and self-aware. You'll make good decisions. Just don't try to do everything at once. + +Good luck! 🚀 |
