aboutsummaryrefslogtreecommitdiff
path: root/todo.org
Commit message (Collapse)AuthorAgeFilesLines
...
* feat(ai-rewrite): add directive-picker wrappers around gptel-rewriteCraig Jennings2026-05-161-8/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `gptel-rewrite` is the killer feature for the keep-gptel decision, and it now lives behind two commands instead of the bare call: - `cj/gptel-rewrite-with-directive` (`C-; a r`, replacing the former bare `gptel-rewrite` binding): completing-read on a directive name from `cj/gptel-rewrite-directives`, then rewrite the active region. - `cj/gptel-rewrite-redo-with-different-directive` (`C-; a R`): replay the prior region with a different directive. The region is preserved via markers stored buffer-local on the first call so it survives accept/reject of the prior rewrite. I picked the hook injection approach over an `:after`-advice + state-capture pattern. `gptel-rewrite-directives-hook` is an abnormal hook gptel-rewrite already consults for a per-call system message. Wrapping the call in a one-shot `let`-binding on that hook gives the directive exactly the lifetime of the rewrite and leaves nothing to clean up. Mutating `gptel-directives` globally would mean either restoring it afterward or living with the change -- both worse than the hook. Directives ship inline as a `defcustom` alist with the six names called out in the task -- `terse`, `fix-grammar`, `refactor-readability`, `add-docstring`, `explain-as-comment`, `shorten`. Customization is a `customize-variable` or `setq` away. 9 tests cover the defcustom shape (default names present, bodies non-empty strings), the wrapper (normal path, no-region error, unknown-directive error, last-state recording), and the redo (replays the prior region, errors when no previous, excludes the current directive from the re-pick prompt). `gptel-rewrite` stubbed in tests so no rewrite UI fires.
* feat(ai-quick-ask): add cj/gptel-quick-ask one-shot commandCraig Jennings2026-05-161-9/+31
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | New module `modules/ai-quick-ask.el`. Bound to `C-; a q` via `cj/ai-keymap` ("quick ask"). `cj/gptel-quick-ask` reads a prompt in the minibuffer, creates a transient `*GPTel-Quick*` buffer in `cj/gptel-quick-mode` (a special-mode derivative with `q` / `escape` / `c` bindings), inserts "Q: <prompt>" plus a response marker, then calls `gptel-request` with `:stream t` so the answer streams into the buffer. Doesn't touch `*AI-Assistant*`, doesn't autosave. Two follow-up commands work in the buffer: - `cj/gptel-quick-dismiss` (`q` / `escape`): delete the window and kill the buffer. Idempotent when the buffer is absent. - `cj/gptel-quick-continue` (`c`): extract the prompt + response, seed them into `*AI-Assistant*` under proper org headings (matching the `cj/gptel--fresh-org-prefix` shape), display the side window, then dismiss the quick buffer. 13 tests cover the pure helpers (initial-text shape, response extraction across normal / multi-line / no-marker / empty inputs, seed-text shape), the ask path (buffer created in right mode, prompt recorded, gptel-request called, empty-prompt error), the dismiss path (kills buffer / no-op when absent), and the continue path (seeds `*AI-Assistant*`, dismisses quick buffer, errors outside a quick buffer). `gptel-request` is stubbed in tests so nothing hits the network.
* feat(ai-conversations): add cj/gptel-autosave-toggle with [AS] mode-line ↵Craig Jennings2026-05-161-6/+18
| | | | | | | | | | | | | | | | | | | | | | | | | indicator `cj/gptel-autosave-enabled` flipped to t inside the save/load entry points with no way back off short of editing the variable or clearing the buffer, and no visible indicator that it was on. Two pieces: - `cj/gptel-autosave-toggle` flips the buffer-local state in the current GPTel buffer. Bound to `C-; a A` via `cj/ai-keymap` (which-key: "toggle autosave"). When autosave is OFF and no filepath is configured yet, the command prompts to save the conversation first so a save target exists; otherwise it just flips the bit. - `cj/gptel-autosave-mode-line-format` surfaces " [AS]" in the mode-line when autosave is on, blank when off. Installed via a `gptel-mode-hook` so every GPTel buffer picks it up. The install helper is idempotent. 6 new tests cover enable/disable paths, the no-filepath prompt path, the not-a-gptel-buffer error path, the mode-line format evaluation, and the install idempotence.
* test(gptel-tools): cover the helpers across the five remaining toolsCraig Jennings2026-05-161-12/+33
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The gptel-tools files had zero direct coverage outside of `update_text_file`, which landed with its rewrite earlier this session. This commit adds 52 tests across the five other tools. For three of the tools the helpers were already top-level defuns (`read_text_file`, `list_directory_files`, `move_to_trash`). The other two had their main bodies inlined into the `gptel-make-tool` lambda -- I extracted them so the work is testable without mocking gptel itself: read_buffer.el -> `cj/read-buffer--get-content` write_text_file.el -> `cj/write-text-file--run` plus `--validate-path`, `--backup-name`, `--ensure-parent` Test files, by tool: - read_buffer.el (5 tests): normal, empty, buffer-object, text-property-stripping, missing buffer. - write_text_file.el (10 tests): validate-path, backup-name shape, ensure-parent (creates missing / rejects unwritable), run with normal / overwrite / existing-no-overwrite / empty content / outside-home. - read_text_file.el (12 tests): validate-file-path (normal + three error shapes), metadata plist shape, size limits (no-op / hard cap / warning bypass with no-confirm), binary detection (text vs null-byte), special-type EPUB and generic-binary paths. - list_directory_files.el (15 tests): mode-to-permissions (file / dir / executable), get-file-info (file / directory), extension filter (keep / drop / always-dir / nil-extension), format-file- entry, list-directory flat / recursive / error, format-output with and without files. - move_to_trash.el (10 tests): unique-name (no conflict / conflict with timestamp / no-extension), validate-path (HOME / /tmp / outside / critical-dir / missing), perform on file and directory. Each test file uses the same load-path / gptel-stub idiom (`eval-and-compile` block, gptel stub when the real package isn't available) so the byte-compile hook is happy.
* test(ai-conversations): add 36 ERT tests covering helpers and entry pointsCraig Jennings2026-05-161-12/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | ai-conversations.el shipped without direct tests. This file covers every helper and interactive entry point across Normal / Boundary / Error. Helpers: `cj/gptel--slugify-topic` (ASCII, empty input, all-special, unicode stripped, idempotent, trim, digits); `cj/gptel--timestamp- from-filename` (normal decode, year-edge boundaries, malformed inputs returning nil); `cj/gptel--existing-topics` and `cj/gptel-- latest-file-for-topic` (multi-topic / multi-timestamp temp dirs, empty dir, missing dir, prefix-overlap isolation); `cj/gptel-- conversation-candidates` (newest-first and oldest-first sort order, display-string shape, error on missing dir); `cj/gptel--save-buffer- to-file` (visibility headers prepended, round-trip through `cj/ gptel--strip-visibility-headers`). Autosave: post-response hook saves only when gptel-mode + enabled + filepath are all set; autosave-after-send swallows write errors via `message` instead of signaling; the install-once guard prevents double-registration. Interactive entry points: save/delete exercised via `cl-letf` stubs on `completing-read` and `y-or-n-p`. Per-test temp directories; no writes outside them.
* fix(ai-config): hook gptel-magit wiring per-feature, not on magitCraig Jennings2026-05-161-10/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | The wiring keyed on `with-eval-after-load 'magit` fires while two of its three references are still undefined. `magit.el` calls `(provide 'magit)` BEFORE its `cl-eval-when (load eval)` block requires `magit-commit` and `magit-stash`. At that moment the `magit-commit` transient prefix doesn't exist, and `transient-append-suffix` silently no-ops on missing prefixes (default `transient-error-on-insert-failure` is nil). The "g Generate commit" and "x Explain" suffixes never landed. Only the M-g binding worked, because `git-commit` IS required before provide. Three per-feature hooks replace the single `'magit` hook: one each on `git-commit`, `magit-commit`, and `magit-diff`. Each hooks the exact dependency the wiring needs, side-stepping the load-order race entirely. The companion test was rewritten to check `after-load-alist` registration rather than drive the hooks through `provide`. Emacs 30 batch mode doesn't fire registered `eval-after-load` callbacks on `provide` alone -- only an actual `load` does. Inspecting the registration is the stronger guard anyway: the regression is "a single `'magit` hook," and the right shape of that check is "no entry under `magit`, entries under `git-commit`, `magit-commit`, `magit-diff`."
* feat(gptel-tools): wire update_text_file as a local tool with testsCraig Jennings2026-05-161-12/+17
| | | | | | | | | | | | | | | | | | | | | I rewrote `update_text_file.el` in pure Elisp. The previous version shelled out to sed for everything, had a stray quote terminator at EOF (line 149) that broke loading, produced literal backslash-n where actual newlines were expected, and prompted via `y-or-n-p` redundantly with gptel's own `:confirm t` flag. The five operations -- replace, append, prepend, insert-at-line, delete-lines -- split into pure string transforms that test without touching the disk. The file-level wrapper validates the path, enforces a 10MB size limit, takes a timestamped backup, and writes atomically. No backup is created when the operation is a no-op. Patterns are literal substrings (not regex) so the model can't trip over metacharacter quoting. `tests/test-update-text-file.el` covers Normal / Boundary / Error per operation plus the file-level wrapper. 48 tests green. Added `update_text_file` to `cj/gptel-local-tool-features` so gptel exposes the tool after restart.
* chore(todo): archive resolved gptel fixesCraig Jennings2026-05-161-19/+17
| | | | | Move the two DONE entries (gptel-magit install + gptel org-mode prompt-buffer tab-width) from Emacs Open Work to Resolved.
* chore(todo): close gptel org-mode tab-width fixCraig Jennings2026-05-161-1/+2
|
* docs(todo): Add org-element--list-struct gptel magit bugCraig Jennings2026-05-161-1/+13
|
* chore(todo): close transient-setup gptel-magit fixCraig Jennings2026-05-151-1/+2
|
* fix(ai-config): Ensure gptel-magit is installed via use-packageCraig Jennings2026-05-151-0/+6
| | | | | | | Replace raw autoload calls with a `use-package` declaration so `use-package-always-ensure` installs gptel-magit on machines that haven't run `package-install`, fixing the "Cannot open load file" error on transient setup.
* fix(flycheck): correct abbrev-mode no-arg toggle in cj/prose-helpers-onCraig Jennings2026-05-151-90/+517
| | | | | | | | | | | | | | | | | The shape (if (not (abbrev-mode)) (abbrev-mode)) calls abbrev-mode with no argument -- that's the toggle signature, not a query. When the mode was already on the function flipped it off then on instead of being a no-op. Replaced with (unless (bound-and-true-p VAR) (MODE 1)) for both abbrev-mode and flycheck-mode. 4 ERT tests cover both-off, both-on, and the two mixed states. Also ran the module hardening pass across 24 newly-added modules, renamed the six completed Review sub-tasks to Harden, filed 11 new findings under their Harden parents, and broke three design specs (EMMS-free music, dev F-keys, dev-setup-project) into 20 dependency-ordered sub-tasks via parallel subagents. Verified the sqlite finalizer bug from 2026-04-26 is gone and closed its tracking entry.
* chore(todo): wrap-up archive + lint passCraig Jennings2026-05-151-81/+78
| | | | | | `--archive-done` moved two completed level-2 PROJECTs into Resolved: the `<cj` universal yasnippet conversion and the LSP file-watch ignored-directories task — both closed earlier this session. `lint-org` applied a small batch of mechanical heading-line merges. The remaining judgment items (broken file links + one invalid fuzzy link) went to the lint follow-ups file for later review. `--sync-child-priority` is a no-op now that the two top-level review PROJECTs carry `:no-sync:` and the inheritance fix lives upstream in claude-templates.
* chore(todo): close <cj universal yasnippet projectCraig Jennings2026-05-151-6/+7
| | | | | | | | | | | All four sub-tasks complete, parent advances to DONE + CLOSED: - Wired yasnippet for universal availability (yas-global-mode + the fundamental-mode extras hook). - Created the <cj snippet at snippets/fundamental-mode/. - Removed the org-tempo cj entry. - Audited existing per-mode snippets — all 28 are correctly mode-scoped, no movers. Sub-task headings landed as dated event-log entries per todo-format.md's depth-based completion rule. The parent stays task-shaped at level-2 for agenda visibility.
* chore(todo): track conversion of <cj structure template to universal yasnippetCraig Jennings2026-05-151-0/+66
| | | | | | Today <cj only expands in org-mode via org-structure-template-alist. A Claude skill scans for the literal #+begin_src cj: comment marker across files, so I need to insert the exact same text in any buffer regardless of major mode. The new task captures four sub-tasks: wire yasnippet to yas-global-mode + activate fundamental-mode as an extra mode in every buffer, create the snippet at snippets/fundamental-mode/, remove the now-redundant org-tempo entry from modules/org-babel-config.el:144, and a smaller follow-up audit of existing per-mode snippets that should probably live in fundamental-mode/.
* chore(todo): expand Gptel Work project with concrete planCraig Jennings2026-05-151-16/+97
| | | | | | | | | | The Gptel Work heading was a one-line placeholder. I filled it in with nine sub-tasks after deciding to keep gptel for one-off conversations, impromptu help, and the rewrite-region helper (workflow distinct from the F9 ai-vterm agents, so per-project sessions stay uncluttered). Bumped the parent to PROJECT [#B] and merged the standalone "Investigate gptel-magit not working properly" task in as a sub-task — the gptel-magit work belongs with the rest of the gptel surface. Four [#B] work items: wire the existing update_text_file tool into cj/gptel-local-tool-features, fix the three gptel-magit triggers, add ERT coverage for ai-conversations.el (zero today), add ERT coverage for the gptel-tools .el files (also zero). Five [#C] proposals for review: research and shortlist additional gptel tools, promote gptel-rewrite ergonomics with a directive picker, build a saved-conversations browser, add a one-shot quick-ask command, and ship an autosave toggle + mode-line indicator.
* chore(todo): close LSP file-watch ignore-list taskCraig Jennings2026-05-151-38/+4
| | | | The implementation shipped 2026-04-26 in 781b46e (cj/lsp-file-watch-ignored-extras plus the hook in modules/prog-lsp.el, 10/10 tests green). The manual smoke check in the dashboard MVP and the redundant .dir-locals.el cleanup on velox are tracked separately as active reminders, so todo.org doesn't need to carry the VERIFY state.
* chore(todo): mark Consolidate shared utility helpers as doneCraig Jennings2026-05-151-135/+157
| | | | | | | | | | | All five children shipped earlier this month but were left tagged TODO/VERIFY. I verified each against the repo, marked them DONE with their actual closure dates, and closed the PROJECT today. Children closed: - Write full utility consolidation design spec — 2026-05-04 (b3ef232a) - Inventory private helpers across modules — 2026-05-10 (502bcf41) - Extract executable lookup with warning helper — cj/executable-find-or-warn in system-lib.el (c75e36f4) - Extract argv-based process runner helper — cj/process-output-or-error and cj/git-output-or-error in system-lib.el (57e558ce) - Extract Org-safe text sanitizers — cj-org-text-lib.el (0f9e3087)
* chore(todo): archive completed work, lint, and rebalance review-project priorityCraig Jennings2026-05-151-575/+568
| | | | | | | | I ran the wrap-up hygiene that the previous session skipped. `--archive-done` moved 7 DONE subtrees out of Open Work into Resolved. `lint-org` applied 8 mechanical heading-line merges. 12 remaining judgment items (mostly broken file links and one malformed timestamp) went to the lint follow-ups file for later. I tagged the two top-level review projects `:no-sync:` so their subtrees stop cascading priority bumps — `:refactor:no-sync:` on the architecture review project and `:review:no-sync:` on the module-by-module review project. The latter also dropped from `[#A]` to `[#B]`. It was sitting at A only because the cascade was forcing it. B is where the work belongs now that the opt-out works.
* chore(todo): re-review module-by-module pass — 32 new findings + newly ↵Craig Jennings2026-05-151-0/+371
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | added modules Second-pass review of the existing six review tracks (foundation, custom editing, UI / navigation, Org workflow, programming workflow, integrations) walked each track as if it had not been reviewed before. Existing child tasks were deliberately excluded from re-reporting; only concrete, file-cited, actionable findings not already on the parent project's task list were filed. Findings filed: - Foundation (5): duplicate user-home-dir constant; redundant eval-when-compile alongside autoload in system-defaults; defcustom conversions for cj/debug-modules and cj/use-online-repos; surface the custom-file trash-binning; name package-archive priorities. - Custom editing (6): region-or-buffer scope inconsistency between text-enclose and ordering helpers; trailing-newline preservation in custom-ordering; non-file-buffer guard for cj/duplicate-line-and-comment; idempotent advice setup in external-open; comment-delimiter validation in custom-comments; state-machine coverage for cj/title-case-region. - UI / navigation (9): popper-mode :init activation defeats :disabled t; vc-git--symbolic-ref fallback in modeline; theme-aware face in cj/display-available-fonts; TTY-first frame race in font setup; per-profile cache in mousetrap-mode keymap rebuilds; symlink-aware VC modeline cache invalidation; C-s binding shadows isearch; cursor-color hook guard for non-GUI frames; nerd-icons advice deferral via with-eval-after-load. - Org workflow (3): de-duplicate org-protocol handler registration in org-webclipper; validate :url and :title in cj/org-protocol-webclip; replace global cj/webclip-current-* with structured per-invocation state. - Programming (6): load-time executable-find checks for prettier and pyright; idempotent server-after-make-frame-hook in keyboard-compat; dev-fkeys F6 typescript runner clause; prog-lsp eldoc-provider removal scope; externalize flycheck LanguageTool script path; externalize latex-config Zathura viewer. - Integrations (2): markdown-preview httpd-start side effect; externalize hardcoded SSH hostnames in eshell-config. Plus: a new "Review newly added modules" sibling task lists all 24 modules that were either added after the parent task was written (post-2026-04) or fell outside the original review-track scope lists. Each is routed to its target track; module-specific findings are filed under the relevant track above. The integrations track re-review subagent derailed mid-run; rather than re-issue it, the track's existing 16 child tasks plus the newly-added-modules findings are deemed adequate coverage. Future re-review passes can revisit if needed.
* chore(todo): close gptel-toggle + buffer-source follow-up bugsCraig Jennings2026-05-151-30/+37
| | | | | | | | | | | | | | | Both follow-up sub-TODOs filed earlier today are resolved: - cj/toggle-gptel cross-module boundary is now an explicit autoload declaration in ai-vterm.el; make compile is clean and a regression test in test-ai-vterm--f9-in-vterm.el asserts the contract. - Info-mode dispatcher in cj/buffer-source-functions now returns the full org bracket-link form [[info:(manual)Node][(manual) Node]]; the existing .info.gz test asserts the new form and a new boundary test covers the uncompressed .info path. Parent tasks return to DONE. Sub-TODOs become dated done headings recording the actual work done.
* chore(todo): housekeeping — music spec closeout + module review progressCraig Jennings2026-05-151-11/+112
| | | | | | | | | | | | | | | | | | | | | | | Three related housekeeping updates that piled up during the session. The "Write spec on what's needed for music-config not to depend on EMMS" task is DONE — spec lives at docs/design/music-config-without-emms.org. Adds a follow-up TODO to implement the spec, with the complexity and time estimates and the acceptance checks the spec already defines. The module-by-module review project moves from PROJECT to DOING. All six review tracks (foundation, custom editing utilities, UI and navigation, Org workflows, programming workflows, integrations and applications) move to DOING with completion-review notes appended under each. The notes summarize what was re-checked, what coverage now exists, and which child tasks are still actionable. Two new sub-TODOs add focused test coverage: - "Add UI/navigation runtime smoke coverage" — font-config, modeline-config, popper-config policy. - "Add smoke coverage for lightweight programming modules with no direct tests" — prog-general, prog-lisp, prog-training.
* chore(todo): reopen gptel-toggle and buffer-source tasks with follow-up bugsCraig Jennings2026-05-151-4/+32
| | | | | | | | | | | | | | | | | | | | Two recent DONE tasks turned out to have follow-up issues worth tracking explicitly instead of leaving them in the closed pile. The gptel-toggle work (=M-<f9>= rebind) now triggers a make compile warning that =cj/toggle-gptel= is not known to be defined when ai-vterm.el loads. The binding still works in normal startup because ai-config.el loads later, but the cross-module load-order dependency should be made explicit via an autoload declaration plus a test that loads ai-vterm.el without preloading ai-config.el. The buffer-source extension shipped an Info-mode dispatcher that copies =info:(manual)Node= rather than the documented org-style bracket link =[[info:(manual)Node][label]]=. The output is a valid org link target but not the labeled form a Notes paste would expect. Both parent tasks move back to DOING with sub-TODOs that name the remaining work, the file/test to update, and the commands to re-run.
* test(architecture): guard top-level timers + add startup-contract smoke testCraig Jennings2026-05-151-1/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | Add a tiny source-level architecture suite at tests/test-architecture-startup-contracts.el with two checks: - Only keybindings.el may globally own the exact C-; prefix. Catches accidental cross-module rebinding before it ships. - Top-level timer scheduling (run-with-timer / run-at-time / run-with-idle-timer) must be guarded by (unless noninteractive ...) so requiring a module in batch / test mode does not schedule startup timers. Timer calls inside defuns are exempt -- the test only rejects forms that execute their body when the module loads. Four modules had unguarded top-level timer scheduling and would have tripped the new test. Wrap their startup hooks/timers in (unless noninteractive ...): - modules/org-agenda-config.el: 10s idle cache build - modules/org-refile-config.el: 5s idle cache build - modules/quick-video-capture.el: after-init-hook + 2s fallback - modules/wrap-up.el: emacs-startup-hook bury-buffers delay The contract being protected is "requiring a module in batch should not start a clock running." Test failures will now point straight at the offending file/form.
* feat(coverage): report modules missing from SimpleCov + project-module scoreCraig Jennings2026-05-151-5/+50
| | | | | | | | | | | | | | | | | | | | | | | | | =make coverage= used to print a line-weighted percentage that only saw files SimpleCov instrumented. 104 modules existed on disk but only 49 appeared in =.coverage/simplecov.json=, so the headline number was flattering: untouched modules counted for nothing. The summary script now adds two things on top of the existing report: - A =Not in SimpleCov report= section listing modules present under =modules/*.el= but absent from the SimpleCov output. Missing-module detection is exactly direct =modules/*.el=; subdirectories and =.elc= files are ignored. - A =Project module coverage= line that is module-weighted across every direct =modules/*.el= file. Tracked modules contribute their per-file coverage percentage; missing modules contribute 0%. The original line-weighted SimpleCov percentage stays as the =instrumented coverage= number. The new module-weighted score is the honest project-level reading: missing modules count as 0% without inventing a fake executable-line denominator for them. Tests assert the missing-module section, the new percentage, and the ignore rules for .elc / nested files.
* docs(design): rewrite flycheck modeline customization specCraig Jennings2026-05-151-21/+22
| | | | | | | | | | | | | | | | | | Replaces the .ai/ draft (2025-11-14) with a corrected and tightened version under docs/design/. The earlier draft had stale line numbers pointing at a modeline-config.el layout that no longer exists, conflated Option 3's risky-local-variable requirement with Option 4's inline (:eval ...) approach, and missed the active-window gating convention used by the rest of the modeline. The new spec uses concrete line refs against current code, calls out flycheck-mode-line-color (which the old draft missed), recommends calling flycheck-mode-line-status-text directly instead of returning the nested (:eval ...) cons, and gates the segment to active window for consistency with cj/modeline-vc-branch and cj/modeline-misc-info. todo.org task points at the new path and drops the broken docs/flycheck-modeline-customization-spec.org link.
* docs(design): add company-to-corfu migration specCraig Jennings2026-05-151-5/+8
| | | | | | | | | | | | | | | | | | Replaces a thin third-party config snippet (one use-package corfu + one use-package cape, with no migration steps and no prescient piece) with a full spec covering the current company stack: corfu, cape, corfu-popupinfo, kind-icon, corfu-prescient. Maps every current company setting to its corfu equivalent (idle-delay, prefix-length, tooltip-limit, wrap, require-match, global-mode exclusions, doc popups, icon kinds, prescient sort). Walks the per-module fixups -- selection-framework, mail-config, ledger-config, latex-config, eshell-config, and the three prog-* mode hooks. Adds a test plan and risks section. todo.org points at the new doc; the broken :COMPLETE_CONFIG: property (which referenced the wrong line range in someday-maybe) is gone.
* feat(custom-buffer-file): extend buffer-source dispatch to mu4e and InfoCraig Jennings2026-05-151-1/+3
| | | | | | | | | | | | | | | | | Add two dispatchers to cj/buffer-source-functions so C-; b p yields a useful link form in two more major modes. mu4e-view-mode returns "mu4e:msgid:<id>" so the result pastes into org as a clickable link and matches mu4e's own org-protocol handler. Falls through to buffer-file-name when point isn't on a real message. Info-mode returns "info:(manual)node" -- the form org-info-store-link produces. file-name-base only strips one extension, so a compressed "emacs.info.gz" comes back as "emacs.info"; trim the trailing ".info" to get the bare manual name. Falls through when Info hasn't populated its current-file / current-node vars yet. Tests cover normal + boundary fallthrough for each new mode.
* chore(todo): mark org-noter insert-note rebind DONECraig Jennings2026-05-151-16/+3
|
* chore(todo): mark calibredb-epub defun-dedup DONECraig Jennings2026-05-151-1/+23
|
* chore(todo): mark buffer-source dispatcher DONE; file follow-up for extra modesCraig Jennings2026-05-151-1/+52
|
* chore(todo): brainstorm buffer-source extensions; correct EPUB nit to DONECraig Jennings2026-05-151-25/+102
| | | | | | | | | | | | | | | Modify C-; b p: add a dated subheader under the task with ideas for extending the buffer-source dispatcher beyond audio files -- three tiers (high-leverage / occasional / skip) covering eww, elfeed, mu4e, org-mode-at-heading, dired/dirvish, doc-view, magit-log, xref/grep, image-mode, archive-mode, plus an implementation sketch (dispatch alist on major-mode with buffer-file-name fallback) and a proposed rename to cj/copy-buffer-source-as-kill. EPUB centering nit: was marked CANCELLED, but the visual-review outcome was actually fine and the task is correctly closed as done (not abandoned). Flip CANCELLED -> DONE; CLOSED timestamp stays since that's when the work-state finalized.
* chore(todo): mark M-F9 gptel-toggle refactor DONECraig Jennings2026-05-141-2/+19
|
* chore(todo): mark gptel model refresh DONECraig Jennings2026-05-141-7/+30
|
* chore(todo): queue gptel model refresh + C-; b p source extensionsCraig Jennings2026-05-141-9/+18
|
* chore(todo): archive today's DONE work + sync child prioritiesCraig Jennings2026-05-141-545/+536
| | | | | | | | | | | Five level-2 subtrees moved into the Resolved section: - Surface org narrowing + sparse-tree under C-; O - F9 toggle restores single-window layout (older) - AI-vterm scrollback history replaces agent buffer (older) - Add ERT coverage for modules below 70% - Fix Python tree-sitter font-lock query syntax error Five child priorities bumped to match their parents.
* chore(todo): mark org narrowing + sparse-tree task DONECraig Jennings2026-05-141-1/+14
|
* chore(todo): add task to surface org narrowing + sparse-tree under C-; OCraig Jennings2026-05-141-0/+42
|
* chore(todo): mark dashboard rebalance DONECraig Jennings2026-05-141-1/+14
|
* chore(todo): mark video-T transcription task DONECraig Jennings2026-05-141-1/+2
|
* chore(todo): add task to extend dired T to transcribe videosCraig Jennings2026-05-141-0/+39
|
* chore(todo): close the coverage-below-70 parent + two child tasksCraig Jennings2026-05-141-28/+45
|
* chore(todo): close Python tree-sitter predicate bug as upstream-resolvedCraig Jennings2026-05-141-7/+9
| | | | | | | | | | | | | | | | | | | | The treesit-query-error redisplay flood diagnosed 2026-04-26 no longer reproduces. Versions: emacs 30.2-3 (was 30.2-2 at the time of the investigation, upgraded 2026-05-03), tree-sitter 0.26.8 (unchanged). The upstream Emacs version string is unchanged, but the Arch package revision bump most likely carries a downstream patch to treesit.c's predicate translation. Verified by re-running the documented repro: the exact failing query from python.el captures cleanly via `treesit-query-capture', and `font-lock-ensure' on a real .py file under `python-ts-mode' returns with no `treesit-query-error'. No local override needed. Mark the todo.org entry DONE, fix the stale `inbox/' path on the investigation-doc link (file now lives under `docs/'), update the cross-reference from the grammar-bootstrap task to note this no longer blocks it, and append a RESOLVED 2026-05-14 footer to the investigation doc so future-me can see why it got closed.
* chore(todo): reconcile test-coverage tracking with current stateCraig Jennings2026-05-141-35/+75
| | | | | | | | | | | After this session's coverage push (68.8% -> 86.5%), 28 of the 30 child modules listed in the coverage-below-70% task have crossed the threshold. Mark them DONE with their new percentages, leave the two genuinely-blocked modules (system-defaults.el at 8.3% and system-commands.el at 69.4%) as TODO with notes explaining the instrumentation-gap reason each is stuck. Also: drop the stray =p= from the parent heading.
* chore(todo): mark journal-save fix DONECraig Jennings2026-05-141-0/+32
|
* feat(org-agenda): add VERIFICATION and IN-PROGRESS blocks around SCHEDULECraig Jennings2026-05-131-1/+46
| | | | | | | | | | The main "d" agenda view grows two new blocks. A VERIFICATION block lists tasks in the VERIFY TODO state, placed just above the day's SCHEDULE. An IN-PROGRESS block lists tasks in the DOING TODO state, placed just under SCHEDULE. The full block order is now: OVERDUE -> HIGH PRIORITY -> VERIFICATION -> SCHEDULE -> IN-PROGRESS -> PRIORITY B. Scope matches the other blocks (every entry in `org-agenda-files`). Scheduled and deadlined entries are included -- a VERIFY task with a date appears in both VERIFICATION and SCHEDULE, mirroring how HIGH PRIORITY behaves. Habits are skipped via `cj/org-skip-subtree-if-habit`; PROJECT-keyword parents wouldn't match `(todo "VERIFY")` exact-state filters anyway, so no extra skip there. Two new header defvars (`cj/main-agenda-verify-title`, `cj/main-agenda-doing-title`) for symmetry with the existing four. Both blocks reference the shared `cj/--main-agenda-prefix-format` so a format tweak still lands in one place. Five new tests in `test-org-agenda-config-skip-functions.el` lock the block order, each new block's header / prefix-format / skip-function, and the include-scheduled-entries contract.
* docs(todo): refresh coverage status after 5-module pushCraig Jennings2026-05-131-8/+17
| | | | | | | | | | Coverage rerun after this session's test additions: 67.2% -> 68.8% (4716/6853 lines across 73 files). Four modules crossed the 70% threshold and are marked DONE: browser-config 69.7% -> 81.6%, ui-config 64.5% -> 90.3%, custom-whitespace 64.6% -> 97.6%, jumper 64.6% -> 98.0%. system-defaults stays open with a note: 8 new tests cover its helpers (`cj/disabled`, the gc-threshold hooks, `unpropertize-kill-ring`, `cj/log-comp-warning`) but the gauge still reads 1/12 because the sandboxed `(load ...)` used to skip startup side effects doesn't register with undercover's instrumentation. Closing it needs either a refactor that lets the module load via plain `(require)` in batch, or a different coverage strategy. Other numbers refreshed where they shifted (ui-navigation 8.7% -> 54.2% from prior session, org-agenda-config 60.0% -> 67.3% from this session's project-name category work, etc.).
* refactor(org-agenda): extract main-agenda prefix format into a defvarCraig Jennings2026-05-131-2/+10
| | | | | | `org-agenda-custom-commands` inlined ` %i %-15:c%?-15t% s` four times across the "d" command's overdue / high-priority / schedule / priority-B blocks. New `cj/--main-agenda-prefix-format` defvar holds the literal once; every block now references the symbol so a format tweak lands in one place. Regression test walks the "d" command's blocks and asserts each `org-agenda-prefix-format` cell resolves to the shared symbol -- a block that silently diverges fails the check.
* feat(setup): scripts/setup-telega.sh prepares the docker environment for telegaCraig Jennings2026-05-131-8/+13
| | | | | | Verifies docker is installed and the daemon is reachable, then either pulls a public image (when `TELEGA_DOCKER_IMAGE` is set) or announces the in-Emacs build path (`M-x telega-server-build`) for the user to run once. Telegram auth (phone + verification code) is interactive on first `M-x telega` and not scripted here. Same shape as setup-email.sh: helpers are sourceable for bats, `main` runs only under direct execution. 7 bats tests stub `docker` and `command` so the suite never talks to the real daemon.