diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-20 13:09:18 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-20 13:09:18 -0400 |
| commit | ba85d2450e201060c65f6e6ee0859bdf65e01e64 (patch) | |
| tree | d874987c7323a30a33c6066d5bddfee628ff85b9 | |
| parent | 8cccc2cd64105062ae4558090f11cc5b11e968a4 (diff) | |
| download | dotemacs-ba85d2450e201060c65f6e6ee0859bdf65e01e64.tar.gz dotemacs-ba85d2450e201060c65f6e6ee0859bdf65e01e64.zip | |
chore(todo): file parent task for the remaining refactoring batch
| -rw-r--r-- | todo.org | 124 |
1 files changed, 124 insertions, 0 deletions
@@ -55,6 +55,130 @@ Tags are additive. For example, a small wrong-behavior fix can be =:bug:quick:=, and a feature that requires internal restructuring can be =:feature:refactor:=. * Emacs Open Work +** TODO [#B] Codebase refactoring program — remaining batch :refactor:solo: +Resumes the full-codebase refactoring scan run of 2026-06-20 (8-agent fan-out over +modules/ + scripts/theme-studio/). The goal: apply every scan finding except the +won't-do items, one focused refactor per commit. 20 done and pushed this session +(see =.ai/sessions/= for the 2026-06-20 log); 13 remain, listed below. + +*** Working protocol (apply to every item) +- TDD: write/keep a failing-then-green test; harvest new test seams the refactor opens. +- Behavior-preserving only. If a "dedup" would delete a real test seam or couple + dissimilar code, SKIP it and record why (see skips below). +- Per refactor, verify in this order, then commit + push (no-approvals mode): + 1. =make test-file FILE=<basename.el>= for touched + new tests. + 2. =make validate-modules= (loads all 123 modules; catches load/paren errors). + 3. Init-launch smoke on a throwaway daemon: =emacs --daemon=cj-sNN=, then + =emacsclient -s cj-sNN -e '(emacs-pid)'= to capture the PID, check + =(length features)= = 807 and no init errors in the log, then kill by that + PID (the emacsclient kill-emacs is flaky; pkill -f 'daemon=cj-sNN' + self-matches its own shell — kill the captured PID). + 4. Live-reload the edited module into Craig's running daemon + (=emacsclient -e '(load "/home/cjennings/.emacs.d/modules/<m>.el")'=); skip + the live reload for big use-package modules whose :config restacks (verify via + the fresh smoke daemon instead, as with mail-config). +- Tab-heavy files: =sed -n 'A,Bp' FILE | cat -A= to get exact bytes before an Edit; + write NEW code in the documented 2-space style. +- Shared asset already created: =cj/format-region-with-program= in system-lib.el + (the run-a-formatter-over-the-buffer helper). Reuse it for any further + format-region duplicates. + +*** Remaining — medium extractions +- calibredb-epub-config.el: =cj/nov-update-layout= (~29 lines, nesting 5) — extract + a render-preserving-position helper + a margin/fringe helper; also the =#E8DCC0= + sepia literal repeated 3x in =cj/nov-apply-preferences= → a local binding. Visual; + verify with the reload-and-verify loop. +- ai-term.el: =cj/ai-term= toggle-off pcase arm (~50 of its ~76 lines) — extract the + teardown into =cj/--ai-term-toggle-off (win)=; and the 3x "switch window to + most-recent non-agent buffer" idiom (lines ~813-817, 839-843, 884-887) → + =cj/--ai-term-swap-to-working-buffer=. Behavior-sensitive window logic; existing + tests test-ai-term--single-window-toggle / --collapse-split are the net. +- calendar-sync.el: =calendar-sync--collect-recurrence-exceptions= (~457-504, nesting + 5, a 14-binding let*) — extract =calendar-sync--parse-exception-event (event-str)= + returning the exception plist; the dolist body becomes a thin puthash. Has a + dedicated test (characterization net). +- dirvish-config.el: =cj/dired-create-playlist-from-marked= (nesting 5) — extract a + pure =cj/--playlist-resolve-target= (the name-validate + overwrite-prompt loop), + leaving filter → resolve → write. +- custom-case.el: =cj/title-case-region= (~71 lines, cyclomatic ~16) — write a + characterization test FIRST, then extract =cj/--title-case-word= (the per-word + decision); main loops boundaries and delegates. + +*** Remaining — big single-file (characterization tests first) +- custom-comments.el: the divider/box render-skeleton duplication — simple-divider vs + padded-divider (~40 lines each, differ only in the padding loop) and box vs + heavy-box (~45 each, heavy-box just adds two blank inserts); plus the comment-syntax + prologue repeated 7x and the doubled-semicolon / length-option constants. Extract a + shared emit-prefix helper + a border/text/border emitter parameterized by padding + lambda + extra-blank-lines. Insertion-order-sensitive: characterize each generator's + output before refactoring. The heaviest item. +- dwim-shell-config.el: ~46 =cj/dwim-shell-commands-*= defuns are trapped in the + =use-package dwim-shell-command :config=, so untestable under =make test=. For the + branching ones (=-video-trim= pcase x3, =-text-to-speech= darwin/linux, + =-extract-archive=/zip/tar single-vs-multi), extract each command's command-string + construction into a top-level pure =cj/dwim-shell--<name>-command= (takes prompted + values, returns the template string), leaving a thin interactive wrapper in :config. + Mirrors the existing =cj/dwim-shell--dated-backup-command= pattern. Do the + high-value branching commands; the trivial ones can stay. + +*** Remaining — theme-studio (scripts/theme-studio/) +Suite: =make check= (Python/Node/ERT) + =./run-tests.sh= (browser gates) + +=make check-generated= (byte-identical html) + =make coverage=. After ANY +generate.py-output change, stage theme-studio.html in the SAME commit +(check-generated compares to the working tree, not HEAD). +- app-core.js: =dropdownRowTextColor= is exported + has 4 tests but no runtime caller + (live path computes inline at app.js:82). Decide: wire it into the dropdown popup + row painting, or delete it + its 4 tests. Needs Craig's intent — default to delete. +- generate.py: ~230 lines of module-level build run at import; =face_coverage.py= does + =import generate= just for two constants and pays the whole cost. Wrap the assembly + in =build()= gated behind =__main__=; keep UI_FACES/CATS/COLS cheap module + constants. (The CRITICAL item.) +- capture-default-faces.py: =condition_matches= (166-206) has parallel dict-branch and + list-branch clause checkers encoding the same four rules + constants twice. Normalize + both shapes to one mapping, run one set of checks. NOT in =make check= — verify by + running it. +- face_coverage.py: =bucket_from_source= (118) and =bucket_of_source= (157) duplicate + the elpa/user/builtin path-kind detection. Extract =path_kind(path)= and have both + map its result to their own vocabulary. +- browser-gates.js (HIGHEST RISK — rewrites the harness that verifies everything): + ~39/44 gates copy-paste the =let ok=true;const notes=[];const A=(c,n)=>{...}= setup + + the =document.title=...; result-div= postamble (note format already drifted: 17 use + " | " vs 24 " fails="). Extract one =gate(name, body)= helper. CRITICAL CONSTRAINT: + each gate's =if(...)= MUST keep the literal substring =location.hash==='#NAMEtest'= + because run-tests.sh:76 discovers gates by grepping exactly that — a registry/loop + that hides the hash check breaks discovery (silent false-green). Pair with a + =withSavedState(keys, body)= helper for the ~13 mutating gates' inconsistent + PALETTE/MAP/UIMAP/SYNTAX snapshot-restore (7 mutating gates currently restore + nothing). Verify: all gates green AND a deliberately-broken assertion still FAILS + (prove the harness can't manufacture greens). Also =assertPreviewFaces= for the 3 + copy-pasted preview-face validators (mdtest/mupreviewtest/gnustest). +- theme-studio test files: =plan(overrides)= factory for the ~30 planPaletteGenerator + full-option-literal calls (test-app-core.mjs + test-palette-generator-core.mjs); one + shared =stripExports= (reimplemented 3x in app-core/colormath/app-util tests, must + stay aligned with generate.py's strip per test_generate.py:48); and an + =assertInlinedVerbatim(name)= loop for the 5 inline-integrity cases. + +*** WON'T-DO (do not re-attempt — assessed and rejected) +- theme-studio buildTable/buildUITable/buildPkgTable merge: genuine per-tier divergence + (column order, syntax dual fg/bg dropdowns, ui preview cell, pkg nd markers) + the + =.cells[N]= positional sort coupling make a unified builder MORE complex than the + three explicit ones. Close as won't-do. +- Cross-language test overlap (browser-gates preview gate vs test_generate.py + PackageFaceCoverage): don't merge — would couple a fast Python test to a headless + browser run. A one-line comment in each noting the split is the most that's worth it. + +*** Skipped this run (with reasons — don't redo) +- eshell-config ssh-alias "merge the two helpers": =cj/--eshell-ssh-alias-commands= is + a deliberate pure/effectful split with 3 dedicated tests; merging deletes the seam. +- prog-*-setup boilerplate: only python+webdev share the full pattern; shell/c/elisp/ + common-lisp differ materially. A keyword-arg helper would be less readable. No + premature abstraction. +- erc join-command =cj/erc--ensure-active-connection= extraction: nesting-only on + untestable UI (call-interactively/switch-to-buffer), no test seam, risky tab-rewrite. +- coverage-core =simplecov-executable-lines= vs =parse-simplecov= clone: borderline + MEDIUM, differs only by a =(> hits 0)= predicate; parameterize with a keep-line-p + only if revisiting. Low priority. + ** TODO [#B] Un-pin ghostel from 0.33.0 once upstream fixes #422/#423 :bug: :PROPERTIES: :LAST_REVIEWED: 2026-06-20 |
