aboutsummaryrefslogtreecommitdiff
path: root/docs/design/module-inventory.org
blob: a6a065da18777ca36a621f183967de0109966270 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
#+TITLE: Module Inventory — init.el Load Graph
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-24

* Purpose

Living per-module inventory for the [[file:init-load-graph.org][init.el load-graph refactor]]. The
spec's module-category table is the seed; this file is the per-module truth as
each module is inspected and classified. A module moves from [[*Pending
classification][Pending classification]] into [[*Classified modules][Classified
modules]] once its source has been read and its load-graph header written.

Phase 1 exit criterion: every module required by =init.el= (102 total) is
represented here with a category and target load shape, every eager survivor
has a documented reason, and top-level timer/process/network side effects are
identified. Classification proceeds in batches; the header-validation test
=tests/test-init-module-headers.el= enforces the contract on each classified
module.

This inventory is independent from the helper inventory owned by
=utility-consolidation.org=.

* Status

- Phase 1 (Inventory and Contracts), in progress.
- Batch 1 (Foundation, Layer 1): classified. 7 modules.
- Batch 2 (Text/editing command modules, Layer 2): classified. 9 modules.
- Batch 3 (Core libraries and command modules): classified. 7 modules.
- Batch 4 (UI / core-UX modules, Layer 2): classified. 10 modules.
- Batch 5 (Dev entry-points, diff, help, lint, VC, Layer 2): classified. 9 modules.
- Batch 6 (Programming modules, Layer 2-4): classified. 10 modules.
- Batch 7 (Org modules, Layer 3-4): classified. 13 modules.
- Batch 8 (Domain / integration / optional modules, Layer 2-4): classified. 18 modules.
- Batch 9 (Remaining domain / integration / optional modules, Layer 2-4): classified. 19 modules.
- 102 of 102 modules classified. Phase 1 classification complete.
- No load-order changes have been made; =init.el= keeps its current eager order.

* Legend

Category key (a module may carry two, e.g. =F/S=):

- =F= foundation or shared library/config
- =C= core eager UX
- =P= package configuration (usually hook/command/package loaded)
- =D= domain workflow with a possible eager reason
- =S= startup side-effect / timer / process owner
- =O= optional, entertainment, experimental, rarely used
- =L= pure-ish library / command helpers, easy to load directly

Load shape: =eager= | =hook= | =mode= | =command= | =after-load=.

Direct test load: =yes= | =conditional= | =no= — can the module be loaded
directly in batch without first loading the rest of init?

* Classified modules

** Batch 1 — Foundation (Layer 1)

| Module | Layer | Cat | Current | Target | Runtime requires | Top-level side effects | Direct load |
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =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 | 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 |

Every Batch 1 module stays eager: each satisfies a spec eager-reason condition
(shared helpers, path constants, core Emacs behavior, or the global keymap
owner). Reasons are recorded in each module's load-graph header.

** Batch 2 — Text/editing command modules (Layer 2)

The =custom-*= text-command helpers. Each is eager only to register a =C-;=
submap (or direct bindings) at load; none has a necessary eager reason, so all
are deferral candidates for Phase 3 (registration API) and Phase 4
(command/autoload). Target load shape is command-driven.

| Module | Layer | Cat | Current | Target | Runtime requires | Top-level side effects | Direct load |
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =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 | 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 |
| =custom-text-enclose= | 2 | L/C | eager | command | keybindings (change-inner on demand) | cj/enclose-map under C-; s | yes |
| =custom-whitespace= | 2 | L/C | eager | command | keybindings | cj/whitespace-map under C-; w | yes |

** Batch 3 — Core libraries and command modules

The remainder of init.el's early/core block: shared command libraries and a few
eager side-effect owners.

| Module | Layer | Cat | Current | Target | Runtime requires | Top-level side effects | Direct load |
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =external-open= | 2 | L/D | eager | command | host-environment, system-lib, external-open-lib, cl-lib | none | yes |
| =media-utils= | 3 | D/L | eager | command | system-lib | none | yes |
| =auth-config= | 1 | F/D | eager | eager | system-lib, user-constants | auth-source/epa config | yes |
| =keyboard-macros= | 2 | C/L | eager | command | subr-x, user-constants | none | yes |
| =system-utils= | 2 | L/C/S | eager | eager | system-lib, external-open-lib | 3 global keys, 1 startup hook | yes |
| =text-config= | 2 | C/P | eager | eager | none | 3 add-hook, package config | yes |
| =undead-buffers= | 2 | C | eager | eager | none | 3 global keys (kill-buffer remap) | yes |

** Batch 4 — UI / core-UX modules (Layer 2)

Modules that shape the first interactive frame: theme, font, modeline, window
navigation, completion stack, and landing page. Most have a real first-frame
eager reason and stay eager.

| Module | Layer | Cat | Current | Target | Runtime requires | Top-level side effects | Direct load |
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =ui-config= | 2 | C/S | eager | eager | user-constants | UI defaults, post-command hook, display-buffer-alist | yes |
| =ui-theme= | 2 | C | eager | eager | none | theme load path, theme key | yes |
| =ui-navigation= | 2 | C/P | eager | eager | none | nav keymap, 5 global keys, package config | yes |
| =font-config= | 2 | C/P/S | eager | eager | host-environment, keybindings | 5 global font keys, font-install checks | yes |
| =selection-framework= | 2 | C/P | eager | eager | none | 1 global key, 15 use-package forms | yes |
| =modeline-config= | 2 | C/S | eager | eager | user-constants | 2 add-hook (VC cache) | yes |
| =mousetrap-mode= | 2 | C | eager | eager | cl-lib | 3 add-hook, 1 add-to-list, 1 global key | yes |
| =popper-config= | 2 | C/P | eager | eager | none | package config (enabled-state open question) | yes |
| =dashboard-config= | 2 | C/S | eager | eager | none | builds/opens dashboard buffer at startup | conditional |
| =nerd-icons-config= | 2 | C/P | eager | eager | none | package config | yes |

** Batch 5 — Dev entry-points, diff, help, lint, VC (Layer 2)

Command entry points and package config for the development workflow: coverage
(F7), F-keys (F4/F6), diff, help, lint, the ERT runner, and Magit.

| Module | Layer | Cat | Current | Target | Runtime requires | Top-level side effects | Direct load |
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =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, 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 | 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 |

** Batch 6 — Programming modules (Layer 2-4)

prog-general owns the shared programming defaults and tree-sitter/LSP policy and
stays eager. The language modules are eager only by init order and should load
by major mode (Phase 6); prog-training is optional and already autoloads.

| Module | Layer | Cat | Current | Target | Runtime requires | Top-level side effects | Direct load |
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =prog-general= | 2 | C/P/S | eager | eager | none | 4 add-hook, package config | yes |
| =prog-c= | 3 | D/P | eager | mode | none | 6 add-hook, package config | yes |
| =prog-go= | 3 | D/P | eager | mode | none | package config | yes |
| =prog-lisp= | 3 | D/P | eager | mode | none | 2 add-hook, package config | yes |
| =prog-python= | 3 | D/P | eager | mode | system-lib | package config; warns if pyright missing | yes |
| =prog-webdev= | 3 | D/P | eager | mode | system-lib | package config; warns if prettier missing | yes |
| =prog-json= | 3 | D/P | eager | mode | none | 1 add-hook, package config | yes |
| =prog-yaml= | 3 | D/P | eager | mode | none | 1 add-hook, package config | yes |
| =prog-shell= | 3 | D/P/S | eager | mode | none | 5 add-hook (after-save executable hook flagged) | yes |
| =prog-training= | 4 | O/D/P | eager | command | none | package config (autoloaded) | yes |

** Batch 7 — Org modules (Layer 3-4)

The daily Org workflows (config, agenda, capture, refile, roam) stay eager per
the spec's Phase 6 target. Babel and contacts move to after-load; export,
reveal, drill, noter, webclipper, and hugo become command-loaded. The agenda
and refile idle-timer caches are the side effects the spec tracks separately.

| Module | Layer | Cat | Current | Target | Runtime requires | Top-level side effects | Direct load |
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =org-config= | 3 | C/D/P | eager | eager | keybindings | org-protocol, cj/custom-keymap binding, package config | yes |
| =org-agenda-config= | 3 | D/S | eager | eager | user-constants, system-lib, cj-cache-lib | add-hook, idle-timer agenda cache | yes |
| =org-babel-config= | 3 | D/P | eager | after-load | none | 1 global key, package config | yes |
| =org-capture-config= | 3 | D/P | eager | eager | none | capture templates, org-protocol handlers | yes |
| =org-contacts-config= | 3 | D/P | eager | after-load | user-constants | 1 global key, package config | yes |
| =org-drill-config= | 4 | O/D/P | eager | command | user-constants, keybindings | drill keymap under cj/custom-keymap | yes |
| =org-export-config= | 3 | D/P | eager | command | system-lib | package config | yes |
| =org-noter-config= | 4 | O/D/P | eager | command | cl-lib, user-constants, keybindings | add-hook, keymap under cj/custom-keymap | yes |
| =org-refile-config= | 3 | D/S | eager | eager | system-lib, cj-cache-lib | idle-timer refile cache | yes |
| =org-reveal-config= | 4 | O/D/P | eager | command | none | package config | yes |
| =org-roam-config= | 3 | D/P/S | eager | eager | user-constants | 1 global key, roam db setup, package config | yes |
| =org-webclipper= | 4 | O/D/P | eager | command | none | org-protocol handler | yes |
| =hugo-config= | 3 | D/P | eager | command | user-constants, host-environment | package config | yes |

** Batch 8 — Domain / integration / optional modules (Layer 2-4)

AI, browser, calendar, ebook, file-manager, shell, IRC, web, games, and other
domain workflows. Almost all are eager only by init order and become command-,
hook-, or mode-loaded. calendar-sync stays eager when its .local.el is present.
flyspell-and-abbrev is the one Core-UX member (text-mode hooks).

| Module | Layer | Cat | Current | Target | Runtime requires | Top-level side effects | Direct load |
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =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, 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 |
| =dwim-shell-config= | 3 | D/P | eager | command | cl-lib | package config | yes |
| =elfeed-config= | 4 | O/D/P | eager | command | user-constants, system-lib, media-utils | package config (elfeed bindings) | yes |
| =erc-config= | 4 | O/D/P | eager | command | cl-lib, keybindings | ERC keymap under cj/custom-keymap | yes |
| =eshell-config= | 3 | D/P | eager | command | system-utils | add-hook, advice-add, package config | yes |
| =eww-config= | 3 | D/P | eager | command | cl-lib | package config | yes |
| =flyspell-and-abbrev= | 2 | C/P | eager | hook | cl-lib | mode-hook package config | yes |
| =games-config= | 4 | O | eager | command | none | package config | yes |
| =gloss-config= | 4 | O/D/P | eager | command | none | package config | yes |
| =httpd-config= | 4 | O/D/P | eager | command | none | package config | yes |
| =jumper= | 4 | O/L | eager | command | cl-lib | jumper keymap | yes |
| =latex-config= | 3 | D/P | eager | mode | none | package config | yes |

** Batch 9 — Remaining domain / integration / optional modules (Layer 2-4)

The last 19 modules: mail, terminals, chat, media capture, package mirror, and
assorted optional tools. mail-config and the daily terminals stay practically
eager; the rest are command/mode/package-loaded deferral candidates. wrap-up
owns the intentional end-of-startup buffer-bury timer.

| Module | Layer | Cat | Current | Target | Runtime requires | Top-level side effects | Direct load |
|--------+-------+-----+---------+--------+------------------+------------------------+-------------|
| =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, 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 |
| =quick-video-capture= | 4 | O/D/S | eager | command | system-lib | org-protocol handler | yes |
| =reconcile-open-repos= | 3 | D/S | eager | command | cl-lib, subr-x | 1 global key | yes |
| =restclient-config= | 3 | D/P | eager | command | none | package config | yes |
| =slack-config= | 4 | O/D/P | eager | command | system-lib, cl-lib | package config | yes |
| =system-commands= | 3 | D/S | eager | command | keybindings, rx | system-command keymap under cj/custom-keymap | yes |
| =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, 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 (resolved in Phase 2)

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
  =eval-when-compile=. The compiled module therefore cannot load standalone —
  it works at startup only because =init.el= requires host-environment and
  user-constants earlier. Phase 2 fix: promote the two =eval-when-compile=
  requires to plain runtime =require=. (Test
  =test-system-defaults-functions.el= was updated to require host-environment
  so the unit loads in isolation; the production fix is still pending.)
- =custom-buffer-file= registers its =C-; b= submap behind =(when (boundp
  'cj/custom-keymap) ...)= and declares =cj/custom-keymap= only via
  =eval-when-compile=. Loaded standalone without keybindings, the =boundp= guard
  is nil and the binding silently drops. That guard is the
  "define-if-not-present" shim the spec warns against. Phase 2/3 fix: require
  keybindings (or use the registration API once it exists) and drop the guard.
- =dev-fkeys= uses the same =(when (boundp 'cj/custom-keymap) ...)= shim plus an
  =eval-when-compile= declaration for its =C-; P= binding, so the binding
  silently drops when loaded without keybindings. Same Phase 2/3 fix.
- =flycheck-config= binds =(:map cj/custom-keymap ...)= through use-package but
  does not require keybindings, so the binding fails when the module loads
  standalone. Phase 2 fix: require keybindings (or move to the registration API).
- =calendar-sync= guards its =C-; g= registration with =(when (boundp
  'cj/custom-keymap) ...)= and does not require keybindings, so the binding
  silently drops standalone. Same boundp-shim pattern. Phase 2/3 fix.
- =video-audio-recording= uses the same =(when (boundp 'cj/custom-keymap) ...)=
  shim for its =C-; r= binding without requiring keybindings. Same Phase 2/3 fix.
- =mail-config= registers =cj/custom-keymap "e"= directly (no boundp guard) and
  does not require keybindings, so it errors standalone rather than degrading.
  Phase 2 fix: require keybindings (or use the registration API).

* Deferred classification

- None. =elfeed-config= was the last deferred module; its tests were rewritten
  to build real =elfeed-entry= structs (so they survive byte-compilation) and it
  is now classified in Batch 8.

* Pending classification

- None. Every module required by =init.el= is classified (102 of 102).