diff options
Diffstat (limited to 'todo.org')
| -rw-r--r-- | todo.org | 40 |
1 files changed, 24 insertions, 16 deletions
@@ -55,8 +55,14 @@ 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] eww User-Agent advice may not inject under Emacs 30 :bug: -The UA-injection advice =my-eww--inject-user-agent= (=modules/eww-config.el:47=) gates on =(derived-mode-p 'eww-mode)= and is an =:around= on =url-retrieve= / =url-retrieve-synchronously=. Its tests (=tests/test-eww-config-user-agent-advice.el=) fail under =make test=: =test-eww-ua-injected-in-eww-buffer= (:21) and =test-eww-ua-replaces-existing-and-keeps-other-headers= (:42) both see no injected UA, because =(derived-mode-p 'eww-mode)= returns nil in the test's temp buffer where the mode is set with a bare =(setq major-mode 'eww-mode)=. Two possibilities: (a) test-only artifact — a bare setq doesn't establish the mode the way =derived-mode-p= now resolves it, so the test should set the mode properly (call =eww-mode=, or set =derived-mode-parent=); or (b) a real Emacs-30 =derived-mode-p= change that means the advice no longer fires in real eww buffers either, so the desktop User-Agent isn't actually sent. Check (b) first: in a live eww page, =M-: (derived-mode-p 'eww-mode)= — if nil, the gate is broken in production (fix to =(eq major-mode 'eww-mode)= or =provided-mode-derived-p=). If only the test is wrong, fix its mode setup. Pre-existing (eww-config + test unchanged this session); surfaced 2026-06-25 running the full suite during the google-keep work. The third test (=test-eww-ua-not-injected-outside-eww=) passes. +** DONE [#C] ai-term test isolation: collapse-split leaks state breaking display-rule :bug:test: +CLOSED: [2026-06-25 Thu] +Root cause found: the display rule's 4th action =cj/--ai-term-display-saved= splits per the globals =cj/--ai-term-last-direction= / =cj/--ai-term-last-size=, captured on the last toggle-off. The collapse-split multi-window and single-window tests call =cj/ai-term= (which captures those globals) but only let-bound =cj/--ai-term-last-was-bury=, so they leaked =last-direction= = below into =display-rule=, which then split below (left-col 0) instead of right (left-col 40). Confirmed by instrumenting: every window/split global was identical fresh vs after-collapse, but the leaked =last-direction= flipped the directional split. Fix: let-bind =cj/--ai-term-last-direction= + =cj/--ai-term-last-size= to nil in both collapse-split tests, isolating the capture-state globals the way the roundtrip test in the same file already does. Full ai-term suite now 158/158 green. +** DONE [#B] eww User-Agent advice may not inject under Emacs 30 :bug: +CLOSED: [2026-06-25 Thu] +Root cause was NOT =derived-mode-p= (that works in both batch and the daemon — my initial guess was wrong). It was the lexical-binding special-var trap: =eww-config.el= is =lexical-binding: t= and the advice =my-eww--inject-user-agent= let-binds url.el's =url-request-extra-headers=, but the file never declared that var special. The byte-compiler bound it lexically, so the injected User-Agent never reached =url-retrieve= and the desktop UA silently dropped in compiled production (eww still worked, just with the default UA). Verified: the byte-compiled advice returned nil before, =t= after. Fix (commit 6131da8e): a top-level =(defvar url-request-extra-headers)= so the compiler treats it as dynamic and the binding propagates. All 3 advice tests pass; live-reloaded. Same class as the json-object-type and the LSP-test special-var traps — a foreign special var let-bound in a lexical file always needs a compile-time defvar/require. +** TODO [#C] dirvish leaves stray buffers; should be single-instance like org-capture :bug: +Dirvish (=super + f=) seems to leave a pile of buffers around — either it isn't being closed cleanly or it spawns a buffer per navigation. Craig wants it to behave like org-capture: one live instance, and re-pressing the shortcut just focuses the existing dirvish window instead of spawning another. Investigate dirvish's session/buffer lifecycle (=dirvish-reuse-session=, the quit behavior, how =super + f= is bound in =dirvish-config.el=); wire it to reuse one session and raise-or-focus on re-invocation, and clean up stray buffers on quit. From the roam inbox 2026-06-24. ** TODO [#B] first f12 doesn't toggle the term window :bug:solo: The first =f12= of a session flashes the terminal open and immediately closes it, as if the toggle fired on then off; a second =f12= then works. Seen across two separate sessions. From the roam inbox 2026-06-24. ** TODO [#B] F12 pops EAT instead of ghostel :feature:studio: @@ -71,6 +77,12 @@ CLOSED: [2026-06-25 Thu] A recurring event declined for just one occurrence synced out with =:STATUS: accepted= (chime then faithfully showed it). Root cause (diagnosed by a chime session, 2026-06-24): =calendar-sync--apply-single-exception= merged the override's =:attendees= but never re-derived =:status=, so the occurrence kept the series master's accepted status, and =calendar-sync--filter-declined= (which keys off =:status=) didn't drop it. Fix (TDD): in =apply-single-exception=, when overriding =:attendees=, re-derive =:status= via =calendar-sync--find-user-status= against =calendar-sync-user-emails=. Four new tests in =test-calendar-sync--apply-single-exception.el= (declined → "declined"; no-attendee override → inherited intact; accepted override → accepted; override without the user → inherited intact); recurrence + find-user-status + integration suites unchanged. Live-reloaded; a manual re-sync ran clean. The specific 2026-06-24 Arusyak occurrence is past now (its RECURRENCE-ID override aged out of the feed), so the live confirmation lands on the next single-occurrence decline. ** PROJECT [#A] Manual testing and validation Exercised once the phases above land. +*** VERIFY ai-term next steps into and attaches a detached session +What we're verifying: =C-; a n= (or =M-SPC=) cycles into a detached ai-term (alive in tmux, no Emacs buffer) and attaches it, not just live buffers. The pure logic is unit-tested; this is the live attach-on-landing check only Craig can run. +- Start agents in two projects so two ai-terms exist, then leave one detached (kill its Emacs buffer while the tmux session stays alive, or after an Emacs restart that leaves =aiv-*= sessions running). +- Confirm one is attached (a live =agent [...]= buffer) and one is detached (its =aiv-= tmux session is alive but has no buffer). +- Press =C-; a n= repeatedly to cycle through the agents. +Expected: the rotation includes the detached agent; landing on it recreates its terminal buffer and reattaches the tmux session (its live output appears), instead of skipping it. Order is stable (by buffer name) and wraps after the last. *** VERIFY Google Keep v1 live setup and first fetch What we're verifying: read-only v1 fetches real Keep notes and renders =data/keep.org= once the one-time gkeepapi + master-token setup is done. The code and 27 tests (12 Python + 15 ERT) are green; this is the live-credential step only Craig can run. - Install the client into the interpreter =cj/keep-python= uses: =pip install gkeepapi= (or pipx). @@ -430,8 +442,8 @@ Config modules hardcode colors that should come from the theme (audit 2026-06-16 - =org-faces-config.el:38-103= defface defaults (~36 hex) — the themeable org-faces theme-studio already overrides; decide whether the defaults should derive from the palette too. *** TODO [#C] theme-studio: custom view-assignment dropdown with lock indicators :feature:studio:next: The view-assignment dropdown is a plain HTML menu. Make it a custom menu colored like the other custom menus, and have it indicate which assignment views have all their elements locked, so the user knows when a view's assignments are done. From the roam inbox 2026-06-16. -*** TODO [#C] theme-studio: move the "clear palette" button :feature:studio:next: -The clear-palette button is too easy to hit by accident (then re-import the JSON to recover). It currently rides with the update-color and palette-generation controls, not with the palette columns. Move it to be left-aligned at the same vertical level as the color-column names. Layout/CSS change in the palette area (app.js / styles.css); visual, so verify by eye. From the roam inbox 2026-06-16. +*** TODO [#D] theme-studio: move the "clear palette" button :feature:studio: +Craig dislikes the current placement (it rides with the update-color and palette-generation controls and is too easy to hit by accident, then re-import the JSON to recover) but has no target placement in mind yet (2026-06-25). Parked until a placement idea lands — the earlier "left-align at the color-column level" was a guess, not a decision. When a target exists: layout/CSS change in the palette area (app.js / styles.css), visual, verify by eye. From the roam inbox 2026-06-16. *** 2026-06-20 Sat @ 05:53:39 -0400 Tightened the elements-table horizontal layout Reduced per-cell padding 12px to 8px across all three tables and shortened the redundant "mode-line-highlight (mode-line hover)" label to "(hover)". The weight/slant narrowing landed with the custom-widget task below. Commit 792e09b5. *** 2026-06-20 Sat @ 05:53:39 -0400 Custom weight/slant dropdowns with previews @@ -1916,13 +1928,8 @@ Pitfalls: - Do not accidentally re-enable UI/doc/sideline behavior that was explicitly disabled for performance. -***** TODO [#B] Add a startup smoke test for LSP config resolution :quick:solo: - -Keep this narrow. A useful test can require the LSP-related modules with mocked -=use-package= side effects and assert that: -- generic defaults are set in one place, -- no duplicate hook entries are installed for the same mode, -- =lsp-enable-remote= remains nil. +***** 2026-06-25 Thu @ 01:53:48 -0400 Added the LSP config-resolution smoke test +=tests/test-prog-lsp.el= (5 ERT tests) pins prog-lsp's load-time invariants: =lsp-enable-remote= stays nil (no auto-start on TRAMP files), the file-watch-ignore defaults live in one idempotent helper (=cj/lsp--add-file-watch-ignored-extras=), the eldoc provider is stripped from the global hook, and no mode holds a duplicate =lsp-deferred= entry. Tests the top-level =:init= + helper surface rather than the =:config= defaults, which defer to lsp-mode's own load under =make test= (the no-package-initialize constraint). Hit and fixed the lexical-binding special-var trap on =lsp-file-watch-ignored-directories= in the test. **** TODO [#B] Gate tree-sitter grammar auto-install behind an explicit policy @@ -2936,11 +2943,12 @@ Brainstorm complete 2026-06-22 — validated design at [[file:docs/design/vamp-m Next: (1) revise the spec to the new direction; (2) spike the risky assumptions (mpd dumb-single-file-player contract; m3u =.desktop= on Hyprland); (3) =/start-work= against the revised spec — pure-helper extraction (review Migration Plan step 1) is the safe first phase. Priority [#C] is a placeholder pending Craig's call. -** TODO [#C] ai-term: step between running ai-terms even when detached :feature:solo:next: +** DONE [#C] ai-term: step between running ai-terms even when detached :feature:solo:next: +CLOSED: [2026-06-25 Thu] :PROPERTIES: :LAST_REVIEWED: 2026-06-22 :END: -The step-to-next-agent family (s-F9 and friends) should cycle to a running ai-term even when that ai-term is currently detached, instead of skipping it. Today the step only lands on attached/visible ai-terms, so a detached-but-running agent gets passed over and there's no keyboard path back to it — re-attach/display it on landing. From the roam inbox. +Implemented 2026-06-25 (commit 79cbccb5): =cj/ai-term-next= now cycles every active agent (a live buffer OR a live tmux session) keyed on the project dir and ordered by buffer name, and stepping onto a detached one attaches it (=cj/--ai-term-show-or-create= recreates the terminal, which reattaches the session). New pure helpers =cj/--ai-term-next-agent-dir= + =cj/--ai-term-active-agent-dirs= with 10 ERT tests; the live-buffer swap path is unchanged. Live check filed under Manual testing and validation. ** TODO [#C] ai-term: multi-backend (Claude / Codex / local ollama) :feature: :PROPERTIES: @@ -3777,11 +3785,11 @@ These may override useful defaults - review and pick better bindings: - M-S-y yank-media (was overriding yank-pop) - M-S-z undo-kill-buffer (was overriding zap-to-char) -** TODO [#C] Slack message buffers in a reused popup window :quick: +** TODO [#D] Slack message buffers in a reused popup window :quick: :PROPERTIES: -:LAST_REVIEWED: 2026-06-21 +:LAST_REVIEWED: 2026-06-25 :END: -Display slack.el message and thread buffers in a dedicated popup window (side or bottom) and reuse that one window instead of spawning a new window per buffer. Likely a =display-buffer-alist= rule (or popper integration) in =modules/slack-config.el=. +Display slack.el message and thread buffers in a dedicated popup window (side or bottom) and reuse that one window instead of spawning a new window per buffer. Likely a =display-buffer-alist= rule (or popper integration) in =modules/slack-config.el=. Status (2026-06-25): =cj/slack--display-buffer= already reuses one non-selected window; the remaining piece is a *dedicated* side/bottom window. Craig's call — keep the current reuse behavior for now and fold the dedicated-window placement into the "Unified popup and messenger UX" work (same window-placement decision should cover Slack, not be solved piecemeal here). ** DOING [#C] google-keep in-editor integration — build, module-to-package :feature: v1 (read-only) implemented and tested (Phases 1-3): the gkeepapi Python bridge (=scripts/google-keep/keep-bridge.py=, 12 tests), the elisp core + =cj/keep-refresh= renderer with atomic writes and async make-process (=modules/google-keep-config.el=, 15 ERT tests), un-orphaned under a =C-c k= prefix, graceful warning when gkeepapi/token/auth is missing. The pure JSON-to-org core is kept extractable per the spec. Live fetch needs the one-time gkeepapi + master-token setup — see "Google Keep v1 live setup and first fetch" under Manual testing and validation. |
