aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/design/module-inventory.org24
-rw-r--r--modules/calendar-sync.el30
-rw-r--r--modules/custom-buffer-file.el12
-rw-r--r--modules/dev-fkeys.el14
-rw-r--r--modules/flycheck-config.el7
-rw-r--r--modules/mail-config.el7
-rw-r--r--modules/system-defaults.el21
-rw-r--r--modules/transcription-config.el3
-rw-r--r--modules/video-audio-recording.el11
-rw-r--r--todo.org19
10 files changed, 59 insertions, 89 deletions
diff --git a/docs/design/module-inventory.org b/docs/design/module-inventory.org
index 6b5d9d1b..fb6a2770 100644
--- a/docs/design/module-inventory.org
+++ b/docs/design/module-inventory.org
@@ -62,7 +62,7 @@ directly in batch without first loading the rest of init?
| =system-lib= | 1 | F/L | eager | eager | none (auth-source on demand) | none | yes |
| =user-constants= | 1 | F | eager | eager | none | file writes: creates configured dirs/files at load | conditional |
| =host-environment= | 1 | F/L | eager | eager | none (battery on demand) | none | yes |
-| =system-defaults= | 1 | F/S | eager | eager | autorevert, server, bookmark, host-environment, user-constants | global setq, display-warning advice, display-buffer-alist entry, one key remap | conditional |
+| =system-defaults= | 1 | F/S | eager | eager | autorevert, server, bookmark, host-environment, user-constants | global setq, display-warning advice, display-buffer-alist entry, one key remap | yes |
| =keyboard-compat= | 1 | F/S | eager | eager | host-environment | adds emacs-startup-hook | yes |
| =keybindings= | 1 | F/C | eager | eager | user-constants, which-key, free-keys | defines cj/custom-keymap + cj/jump-map, binds global keys, which-key labels | conditional |
| =config-utilities= | 1 | C/O | eager | eager | cl-lib, cl-generic, eieio, find-lisp, profiler | defines cj/debug-config-keymap, binds C-c d | yes |
@@ -83,7 +83,7 @@ are deferral candidates for Phase 3 (registration API) and Phase 4
| =custom-case= | 2 | L/C | eager | command | keybindings | cj/case-map under C-; c; remaps capitalize-region | yes |
| =custom-comments= | 2 | L/C | eager | command | keybindings | cj/comment-map under C-; C | yes |
| =custom-datetime= | 2 | L/C | eager | command | keybindings | cj/datetime-map under C-; d | yes |
-| =custom-buffer-file= | 2 | L/C | eager | command | external-open, mm-decode, system-lib | cj/copy-buffer-content-map, cj/buffer-and-file-map; C-; b registration boundp-guarded | conditional |
+| =custom-buffer-file= | 2 | L/C | eager | command | keybindings, external-open, mm-decode, system-lib | cj/copy-buffer-content-map, cj/buffer-and-file-map; C-; b | yes |
| =custom-line-paragraph= | 2 | L/C | eager | command | keybindings (expand-region on demand) | cj/line-and-paragraph-map under C-; l | yes |
| =custom-misc= | 2 | L/C | eager | command | keybindings | align-regexp advice; direct C-; bindings | yes |
| =custom-ordering= | 2 | L/C | eager | command | cl-lib, keybindings (org-config on demand) | cj/ordering-map under C-; o | yes |
@@ -133,11 +133,11 @@ Command entry points and package config for the development workflow: coverage
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =coverage-core= | 2 | C/L | eager | eager | seq, subr-x, system-lib | 1 global key (F7) | yes |
| =coverage-elisp= | 2 | C/P | eager | eager | coverage-core | backend registration | yes |
-| =dev-fkeys= | 2 | C | eager | eager | cl-lib, system-lib | 6 F-key bindings; C-; P boundp-guarded | conditional |
+| =dev-fkeys= | 2 | C | eager | eager | cl-lib, system-lib, keybindings | 6 F-key bindings; C-; P | yes |
| =diff-config= | 2 | C/P | eager | eager | none | package config | yes |
| =help-config= | 2 | C/P | eager | eager | none | 2 global keys, package config | yes |
| =help-utils= | 2 | L/D | eager | command | none | 1 global key, package config | yes |
-| =flycheck-config= | 2 | C/P | eager | hook | none (needs keybindings for :map) | package config; cj/custom-keymap :map binding | conditional |
+| =flycheck-config= | 2 | C/P | eager | hook | keybindings | package config; cj/custom-keymap :map binding | yes |
| =test-runner= | 2 | C/L | eager | eager | ert, cl-lib, keybindings | test keymap under cj/custom-keymap | yes |
| =vc-config= | 2 | C/P | eager | eager | user-constants, keybindings | 2 keymaps under cj/custom-keymap, package config | yes |
@@ -195,7 +195,7 @@ flyspell-and-abbrev is the one Core-UX member (text-mode hooks).
| =ai-config= | 3 | D/P | eager | command | keybindings, system-lib | cj/ai-keymap under cj/custom-keymap | yes |
| =ai-vterm= | 3 | D | eager | command | cl-lib, seq, cj-window-geometry-lib, cj-window-toggle-lib, host-environment | 4 global keys | yes |
| =browser-config= | 3 | D/P | eager | command | cl-lib | 1 global key | yes |
-| =calendar-sync= | 3 | D/S | eager (.local.el) | eager (.local.el) | cl-lib, subr-x, system-lib, cj-org-text-lib | calendar keymap (boundp-guarded), guarded timer/network | conditional |
+| =calendar-sync= | 3 | D/S | eager (.local.el) | eager (.local.el) | cl-lib, subr-x, system-lib, cj-org-text-lib, keybindings | calendar keymap (C-; g), guarded timer/network | yes |
| =calibredb-epub-config= | 4 | O/D/P | eager | command | user-constants, subr-x | add-hook, advice-add, package config | yes |
| =chrono-tools= | 3 | D/P | eager | command | user-constants | package config | yes |
| =dirvish-config= | 3 | D/P | eager | command | user-constants, system-utils, host-environment, system-lib, external-open-lib | 3 add-hook, package config | yes |
@@ -222,7 +222,7 @@ owns the intentional end-of-startup buffer-bury timer.
| =linear-config= | 3 | D/P | eager | command | system-lib | package config | yes |
| =local-repository= | 4 | O/D/P | eager | command | elpa-mirror | none | yes |
| =lorem-optimum= | 4 | O/L | eager | command | cl-lib | none | yes |
-| =mail-config= | 3 | D/P | eager | command | user-constants, system-lib, mu4e-attachments | cj/email-map under cj/custom-keymap, add-hook, 2 advice, 1 global key | conditional |
+| =mail-config= | 3 | D/P | eager | command | user-constants, system-lib, mu4e-attachments, keybindings | cj/email-map under cj/custom-keymap, add-hook, 2 advice, 1 global key | yes |
| =markdown-config= | 3 | D/P | eager | mode | none | package config, org-src lang map | yes |
| =music-config= | 4 | O/D/P/S | eager | command | subr-x, user-constants, keybindings | music keymap under cj/custom-keymap, 1 global key | yes |
| =pdf-config= | 3 | D/P | eager | mode | none | package config | yes |
@@ -234,15 +234,19 @@ owns the intentional end-of-startup buffer-bury timer.
| =telega-config= | 4 | O/D/P | eager | command | keybindings | telega keymap under cj/custom-keymap | yes |
| =tramp-config= | 3 | D/P | eager | package | none | package config | yes |
| =transcription-config= | 4 | O/D/P | eager | command | dired, notifications, system-lib, user-constants | 1 add-to-list | yes |
-| =video-audio-recording= | 4 | O/D/S | eager | command | system-lib | cj/record-map under C-; r (boundp-guarded) | conditional |
+| =video-audio-recording= | 4 | O/D/S | eager | command | system-lib, keybindings | cj/record-map under C-; r | yes |
| =vterm-config= | 3 | D/P | eager | command | keybindings, seq, subr-x, cj-window-geometry-lib, cj-window-toggle-lib | 2 keymaps, 1 global key, 2 add-hook | yes |
| =weather-config= | 4 | O/D/P | eager | command | none | package config | yes |
| =wrap-up= | 2 | S | eager | eager | system-lib | one-shot startup buffer-bury timer | yes |
-* Hidden dependencies found
+* Hidden dependencies (resolved in Phase 2)
-Discoveries that belong to Phase 2 (make dependencies explicit). Recorded here,
-not fixed here.
+Discoveries from classification, all resolved in Phase 2 by making each
+dependency explicit: requiring the owning module (=host-environment=,
+=user-constants=, =keybindings=) and dropping the =boundp= / =eval-when-compile=
+shims. Each consuming module now loads standalone (verified with a fresh
+=emacs --batch (require 'X)= per module). Kept here as the record of what was
+found and fixed; the =Phase 2 fix:= notes below describe the change applied.
- =system-defaults= reads =env-bsd-p= (host-environment) and =user-home-dir=
(user-constants) at *load* time, but declares both only via
diff --git a/modules/calendar-sync.el b/modules/calendar-sync.el
index 4d1ea219..21ef8727 100644
--- a/modules/calendar-sync.el
+++ b/modules/calendar-sync.el
@@ -13,11 +13,8 @@
;; Top-level side effects: defines a calendar keymap and conditionally registers
;; it under cj/custom-keymap; timer and network fetches guarded by
;; config/noninteractive checks.
-;; Runtime requires: cl-lib, subr-x, system-lib, cj-org-text-lib. keybindings is
-;; needed for the C-; g binding but only reached through a boundp guard, so the
-;; binding silently drops standalone. Phase 2 fix.
-;; Direct test load: conditional (C-; g registration skipped without keybindings;
-;; private config optional).
+;; Runtime requires: cl-lib, subr-x, system-lib, cj-org-text-lib, keybindings.
+;; Direct test load: yes (private config optional; degrades cleanly when absent).
;;
;; Simple, reliable one-way sync from multiple calendars to Org mode.
;; Downloads .ics files from calendar URLs (Google, Proton, etc.) and
@@ -87,6 +84,7 @@
(require 'subr-x)
(require 'system-lib) ;; provides cj/auth-source-secret-value (leaf; no ai-config dep)
(require 'cj-org-text-lib)
+(require 'keybindings) ;; provides cj/custom-keymap
(defun calendar-sync--log-silently (format-string &rest args)
"Log FORMAT-STRING with ARGS without requiring the full config."
@@ -1705,18 +1703,16 @@ Syncs all calendars immediately, then every `calendar-sync-interval-minutes'."
"S" #'calendar-sync-start
"x" #'calendar-sync-stop)
-;; Only set up keybindings if cj/custom-keymap exists (not in test environment)
-(when (boundp 'cj/custom-keymap)
- (keymap-set cj/custom-keymap "g" cj/calendar-map)
-
- (with-eval-after-load 'which-key
- (which-key-add-key-based-replacements
- "C-; g" "calendar sync menu"
- "C-; g s" "sync now"
- "C-; g i" "sync status"
- "C-; g t" "toggle auto-sync"
- "C-; g S" "start auto-sync"
- "C-; g x" "stop auto-sync")))
+(keymap-set cj/custom-keymap "g" cj/calendar-map)
+
+(with-eval-after-load 'which-key
+ (which-key-add-key-based-replacements
+ "C-; g" "calendar sync menu"
+ "C-; g s" "sync now"
+ "C-; g i" "sync status"
+ "C-; g t" "toggle auto-sync"
+ "C-; g S" "start auto-sync"
+ "C-; g x" "stop auto-sync"))
;;; Initialization
diff --git a/modules/custom-buffer-file.el b/modules/custom-buffer-file.el
index 67191244..d24c66b9 100644
--- a/modules/custom-buffer-file.el
+++ b/modules/custom-buffer-file.el
@@ -9,10 +9,8 @@
;; by init order; a deferral candidate for Phase 3/4.
;; Top-level side effects: defines cj/copy-buffer-content-map and
;; cj/buffer-and-file-map; conditionally registers the latter under C-; b.
-;; Runtime requires: external-open, mm-decode, system-lib. keybindings is needed
-;; for the C-; b registration but is declared only via eval-when-compile and
-;; guarded by `boundp', so the binding silently drops standalone. Phase 2 fix.
-;; Direct test load: conditional (C-; b registration skipped without keybindings).
+;; Runtime requires: keybindings, external-open, mm-decode, system-lib.
+;; Direct test load: yes (requires keybindings explicitly).
;;
;; This module provides custom buffer and file operations including PostScript
;; printing capabilities.
@@ -42,8 +40,7 @@
;;
;;; Code:
-;; cj/custom-keymap defined in keybindings.el
-(eval-when-compile (defvar cj/custom-keymap))
+(require 'keybindings) ;; provides cj/custom-keymap
(eval-when-compile (require 'ps-print)) ;; for ps-print variables
(declare-function ps-print-buffer-with-faces "ps-print")
(declare-function ps-print-region-with-faces "ps-print")
@@ -541,8 +538,7 @@ Signals an error if:
"<right>" #'cj/window-resize-sticky
"<up>" #'cj/window-resize-sticky
"<down>" #'cj/window-resize-sticky)
-(when (boundp 'cj/custom-keymap)
- (keymap-set cj/custom-keymap "b" cj/buffer-and-file-map))
+(keymap-set cj/custom-keymap "b" cj/buffer-and-file-map)
(with-eval-after-load 'which-key
(which-key-add-key-based-replacements
diff --git a/modules/dev-fkeys.el b/modules/dev-fkeys.el
index 02e8a72e..00bb91ad 100644
--- a/modules/dev-fkeys.el
+++ b/modules/dev-fkeys.el
@@ -8,10 +8,8 @@
;; Eager reason: the F4/F6 developer command entry points.
;; Top-level side effects: six global F-key bindings; conditionally registers a
;; C-; P binding.
-;; Runtime requires: cl-lib, system-lib. keybindings is needed for the C-; P
-;; binding but is declared only via eval-when-compile and guarded by `boundp',
-;; so that binding silently drops standalone. Phase 2 fix.
-;; Direct test load: conditional (C-; P registration skipped without keybindings).
+;; Runtime requires: cl-lib, system-lib, keybindings.
+;; Direct test load: yes (requires keybindings explicitly).
;;
;; Project-aware F-key block for developer workflows:
;;
@@ -54,6 +52,7 @@
(require 'cl-lib)
(require 'system-lib)
+(require 'keybindings) ;; provides cj/custom-keymap
(declare-function projectile-compile-project "projectile" (arg))
(declare-function projectile-run-project "projectile" (arg))
@@ -531,12 +530,7 @@ message."
;; ---------- Bindings ----------
-(eval-when-compile (defvar cj/custom-keymap)) ;; defined in keybindings.el
-
-;; Skip the binding if cj/custom-keymap isn't loaded yet (e.g. when this
-;; module is required directly in batch tests).
-(when (boundp 'cj/custom-keymap)
- (keymap-set cj/custom-keymap "P" #'cj/projectile-reset-cmds))
+(keymap-set cj/custom-keymap "P" #'cj/projectile-reset-cmds)
(keymap-global-set "<f4>" #'cj/f4-compile-and-run)
(keymap-global-set "C-<f4>" #'cj/f4-compile-only)
diff --git a/modules/flycheck-config.el b/modules/flycheck-config.el
index 8932a3ac..5626095c 100644
--- a/modules/flycheck-config.el
+++ b/modules/flycheck-config.el
@@ -10,9 +10,8 @@
;; candidate.
;; Top-level side effects: package configuration via use-package, binds into
;; cj/custom-keymap through use-package :map.
-;; Runtime requires: keybindings is needed for the cj/custom-keymap :map binding
-;; but is not required here; the binding fails standalone. Phase 2 fix.
-;; Direct test load: conditional (needs cj/custom-keymap for the :map binding).
+;; Runtime requires: keybindings.
+;; Direct test load: yes (requires keybindings explicitly).
;;
;; This file configures Flycheck for on-demand syntax and grammar checking.
;; - Flycheck starts automatically only in sh-mode and emacs-lisp-mode
@@ -44,6 +43,8 @@
;;; Code:
+(require 'keybindings) ;; provides cj/custom-keymap (use-package :map below)
+
(defun cj/prose-helpers-on ()
"Ensure that `abbrev-mode' and `flycheck-mode' are on in the current buffer."
(interactive)
diff --git a/modules/mail-config.el b/modules/mail-config.el
index 5050d761..e1ebdfce 100644
--- a/modules/mail-config.el
+++ b/modules/mail-config.el
@@ -10,10 +10,8 @@
;; command-loaded deferral candidate for Phase 5.
;; Top-level side effects: registers cj/email-map under cj/custom-keymap, one
;; add-hook, two advice-add, one global key, package config.
-;; Runtime requires: user-constants, system-lib, mu4e-attachments. keybindings
-;; is needed for the C-; e registration but is not required, so the module
-;; errors standalone. Phase 2 fix.
-;; Direct test load: conditional (needs cj/custom-keymap from keybindings).
+;; Runtime requires: user-constants, system-lib, mu4e-attachments, keybindings.
+;; Direct test load: yes (requires keybindings; mu4e package must be present).
;;
;; I found Aime Bertrand's blog post to be an excellent walkthrough of how to
;; setup a Mu4e config.
@@ -34,6 +32,7 @@
(require 'user-constants)
(require 'system-lib)
(require 'mu4e-attachments)
+(require 'keybindings) ;; provides cj/custom-keymap
;; cj/custom-keymap's real binding is in keybindings.el, which init.el loads
;; first. The use-package org-msg :preface below wraps in eval-and-compile, so
diff --git a/modules/system-defaults.el b/modules/system-defaults.el
index 33d93bbc..8ef6181a 100644
--- a/modules/system-defaults.el
+++ b/modules/system-defaults.el
@@ -11,11 +11,9 @@
;; Top-level side effects: mutates global defaults (many `setq'), advises
;; `display-warning', adds a `display-buffer-alist' entry, remaps one global
;; key.
-;; Runtime requires: autorevert, server, bookmark; host-environment
-;; (`env-bsd-p') and user-constants (`user-home-dir') are read at load but
-;; currently only required via eval-when-compile — Phase 2 to make explicit.
-;; Direct test load: conditional (host-environment and user-constants must load
-;; first; the compiled module cannot resolve them standalone yet).
+;; Runtime requires: autorevert, server, bookmark, host-environment
+;; (`env-bsd-p'), user-constants (`user-home-dir').
+;; Direct test load: yes.
;;
;; Loads during init to set sane defaults: UTF-8 everywhere, quiet prompts, synced clipboards,
;; and hands-off async shell buffers. Nothing to call—just launch Emacs and the environment is ready.
@@ -31,13 +29,12 @@
(require 'server)
(require 'bookmark)
-;; `host-environment' and `user-constants' are loaded earlier in init.el,
-;; so they are available at runtime when this module loads. The
-;; `eval-when-compile' forms here are byte-compile hints to silence
-;; free-variable / free-function warnings when this module is compiled
-;; in isolation; no runtime requires are needed.
-(eval-when-compile (require 'host-environment))
-(eval-when-compile (require 'user-constants))
+;; host-environment (`env-bsd-p') and user-constants (`user-home-dir') are read
+;; at load time below, so require them at runtime, not only at compile time.
+;; init.el already loads them earlier; the explicit requires let this module
+;; load standalone.
+(require 'host-environment)
+(require 'user-constants)
;; -------------------------- Native Comp Preferences --------------------------
diff --git a/modules/transcription-config.el b/modules/transcription-config.el
index 0a4b4b39..566cea49 100644
--- a/modules/transcription-config.el
+++ b/modules/transcription-config.el
@@ -50,9 +50,6 @@
(require 'system-lib) ; provides cj/auth-source-secret-value
(require 'user-constants) ; For cj/audio-file-extensions
-;; Declare keymap defined in keybindings.el
-(eval-when-compile (defvar cj/custom-keymap))
-
;; ----------------------------- Configuration ---------------------------------
(defvar cj/transcribe-backend 'assemblyai
diff --git a/modules/video-audio-recording.el b/modules/video-audio-recording.el
index 38c1931c..cec5df85 100644
--- a/modules/video-audio-recording.el
+++ b/modules/video-audio-recording.el
@@ -10,10 +10,8 @@
;; run only on command (command-loaded target).
;; Top-level side effects: defines cj/record-map and conditionally registers it
;; under C-; r.
-;; Runtime requires: system-lib. keybindings is needed for the C-; r binding but
-;; only reached through a boundp guard, so the binding silently drops
-;; standalone. Phase 2 fix.
-;; Direct test load: conditional (C-; r registration skipped without keybindings).
+;; Runtime requires: system-lib, keybindings.
+;; Direct test load: yes (requires keybindings explicitly).
;;
;; Desktop video and audio recording from within Emacs using ffmpeg.
;; Records from both microphone and system audio simultaneously, which
@@ -109,6 +107,7 @@
;;; Code:
(require 'system-lib)
+(require 'keybindings) ;; provides cj/custom-keymap
;;; ============================================================
;;; Configuration Variables
@@ -1089,9 +1088,7 @@ Changes take effect on the next recording (not the current one)."
map)
"Keymap for video/audio recording operations under C-; r.")
-;; Only bind keys when running interactively (not in batch/test mode)
-(when (boundp 'cj/custom-keymap)
- (keymap-set cj/custom-keymap "r" cj/record-map))
+(keymap-set cj/custom-keymap "r" cj/record-map)
(with-eval-after-load 'which-key
(which-key-add-key-based-replacements
diff --git a/todo.org b/todo.org
index 8c6ab7be..a8b0e83c 100644
--- a/todo.org
+++ b/todo.org
@@ -390,23 +390,12 @@ Built [[file:docs/design/module-inventory.org][docs/design/module-inventory.org]
**** TODO [#B] Annotate elfeed-config load-graph header :refactor:
The single init.el module left unclassified. Its source is read and understood (Layer 4, O/D/P, command-loaded; runtime requires user-constants, system-lib, media-utils) and documented under "Deferred classification" in the inventory, but annotating its header triggers the PostToolUse byte-compile, which breaks =tests/test-elfeed-config-helpers.el=. Blocked on the "Make elfeed-config tests byte-compile-safe" task. Once that lands: add the 7-line header, move the module from "Deferred classification" into a Batch table in the inventory, and add it to the validation allowlist.
-**** TODO [#B] Add explicit module dependencies before changing load order :refactor:
+**** 2026-05-24 Sun @ 18:35:06 -0500 Made hidden module dependencies explicit
+Fixed the seven hidden dependencies the classification surfaced: system-defaults now requires host-environment and user-constants at runtime (was eval-when-compile); custom-buffer-file, dev-fkeys, calendar-sync, and video-audio-recording require keybindings and drop their =(when (boundp 'cj/custom-keymap) ...)= shims; flycheck-config and mail-config require keybindings for their cj/custom-keymap bindings. Removed a dead =eval-when-compile (defvar cj/custom-keymap)= in transcription-config (the var was never used).
-Several modules assume things like =cj/custom-keymap=, path constants, or
-environment predicates already exist. Before deferring load, make each module
-declare what it uses.
+No init.el load-order change — keybindings and the foundation modules already load before these, so the explicit requires are no-ops at startup and only fix standalone/test loading.
-Guidance:
-- Prefer runtime =(require 'foo)= for actual runtime dependencies.
-- Use =eval-when-compile= only for macros or compile-time declarations.
-- Avoid shims like "define this keymap if it does not exist" except in tests.
-- If a module only needs a command from another module, consider =autoload=.
-
-Acceptance criteria:
-- Loading a module directly in batch mode either succeeds or gives a clear
- missing-package error.
-- =make validate-modules= still passes.
-- New tests cover any extracted pure dependency helpers.
+Verified each fix with a fresh =emacs --batch (require 'X)=, then swept all ~100 modules standalone: every one loads or fails only with a clear missing-package message (the spec's Phase 2 exit bar). Full =make test=, =make validate-modules=, and an init smoke all pass. Module headers and the inventory's hidden-dependency section updated to mark the seven resolved.
**** TODO [#B] Defer feature modules behind autoloads, hooks, and commands :refactor: