feat: add application Dock menu#284
Conversation
umputun
left a comment
There was a problem hiding this comment.
two blocking issues before this is ready:
-
agterm/AppDelegate+DockMenu.swift:181- a non-idle session can appear in both Recent Sessions and Sessions Needing Attention, but the Recent path calls onlyfocusActiveSession(). It won't reveal a tagged right or scratch pane, so the same session behaves differently depending on which submenu selected it. CallrevealActiveBlockedPane()for every session selection and remove theneedsAttentionbranch. That helper already falls back to ordinary focus for idle sessions. -
agterm/AppDelegate+DockMenu.swift:44-185- this new AppKit UI has no test coverage. Pls add focused Dock-menu UI tests for menu contents and enabled states, MRU/current-session filtering, attention ordering, nil-sender target invocation, and the captured-window case where window B becomes frontmost before a window A session is selected. The dashboard/zoom stale-action checks should be covered too.
minor:
agterm/AppDelegate+DockMenu.swift:95hardcodes the MRU limit as10, while the existing recent-session surfaces useSessionSwitcher.maxCandidates. Use the shared value here too.- update
README.mdandsite/docs.html. The attention docs still say there are "two more ways," and neither public surface mentions the Dock menu or its last-active-window scope. - update
.claude/rules/menu-actions.mdand.claude/rules/windows.mdfor the new action surface. AddAppDelegate+DockMenu.swiftto the applicable paths and document retained targets, captured store/window scope, the per-window modal check, and synchronous frontmost-window publication.
umputun
left a comment
There was a problem hiding this comment.
two blocking issues and one question remain:
-
project.yml:182-215- the newagtermTeststarget is application-hosted, but the Test action sets neitherAGTERM_STATE_DIRnorAGTERM_CONTROL_SOCKET. Running the focused test launched agterm against the real config and app-support paths and started login shells beforeDockMenuTests.setUp()created its temporary library. It also killed my live control socket. Pls isolate the host process beforeagtermApp.init()runs. The current CI test job runs onlyagtermCore, so add a CI invocation for this target after it is safe to run. -
agterm/AppDelegate+DockMenu.swift:50-77- should New Session, Quick Terminal, and Dashboard use the window captured when the menu opened, or whichever window is frontmost when the item is selected? The current code uses the latter, while README/site promise that all lists and actions stay tied to the captured window. If invocation-time frontmost is intended, pls narrow the docs to session lists/actions. If captured scope is intended, capture A's window/store and add the B-frontmost case for all three actions. -
agterm/AppDelegate+DockMenu.swift:178-180- pane-aware selection is still wrong for an explicitleftstatus or an omitted pane.revealActiveBlockedPane()falls through tofocusActiveSession(), which follows the existingsplitFocused; if the right pane was focused, the Dock jump stays on the right. Set the primary-pane target explicitly for.left/.noneand add cases with the right pane initially focused.
|
FYI: I have run out of weekly credits/limits for my daily-driver claude code and adopted skill, which is helping me review things, for codex. This is the reason why those reviews sound so categorical and demanding, as if codex writes to other models and not to humans. ;) nothing personal. |
No worries, I'm used to Codex. Quick question: have you considered including a review skill or a |
umputun
left a comment
There was a problem hiding this comment.
the three from last round check out. Test-action isolation holds on every route (I ran the target and my state dir, config and socket came back byte-identical), captured window/store scope is right, and .left/omitted targets the primary explicitly now. The round-1 items are in too, except the test coverage below.
agtermTests/DockMenuTests.swift - coverage gaps. the 9 tests cover menu contents, enabled states, MRU order and cap, attention ordering, nil-sender dispatch, and the window-B-frontmost captured scope for all three top-level items plus session selection. Not covered:
- stale dashboard/zoom inertness for the three TOP-LEVEL items.
makeCapturedSessionAction()only builds a session row, so tests 8 and 9 exercise session selection only. Test 6 opens the dashboard on window B, never on captured window A after the menu is built. Nothing proves New Session / Quick Terminal / Dashboard go inert when A enters a modal post-build, which is the casewindows.mdnow documents. - the
.rightreveal branch. Only.scratchand.left/nil appear anywhere in the file, soAppActions+Focus.swift:83-85never runs. The Dock is the fifth caller of that branch. - captured window CLOSED (not just modal) between build and invoke. Nothing calls
library.closeWindow, so thelibrary.store(for:) === storeidentity guard atAppDelegate+DockMenu.swift:169and theweak storecapture are both unexercised. applicationDockMenuwithlibrary == nil, i.e. a Dock right-click before the scene.taskwires it. Thestore = library?.activeStorenil path and thestore == nilsubmenu branch are never hit.- target invalidation across a menu rebuild. No test builds a second menu then invokes an item from the first, which is the one path where a stale item's target is already gone.
separately, testSessionSelectionForcesPrimaryForExplicitAndOmittedLeftPane doesn't prove what the name says. DockMenuTestSurface isn't a GhosttySurfaceView, so focusSplitPane's as? GhosttySurfaceView cast never matches and first responder never moves. Both assertions check only that splitFocused was cleared, which happens at AppActions+Focus.swift:90, before focusSplitPane is called at all. Reasonable limit for a windowless hosted test, but rename it or add a comment so it doesn't read as focus coverage.
question on revealActiveBlockedPane. the fix went into the shared helper, so .left/omitted now clears splitFocused and forces the primary for every caller: sidebar click, ⌥⌘↑↓, first/last, both palettes, auto-follow. The agent-status hook sends --pane left from the primary pane and emits active on ordinary tool use, not only on a block. So a session whose agent is merely working, split hidden with the right pane zoomed, now un-zooms and jumps to the left pane on a plain sidebar click. Should the forced primary be gated on needsAttention (blocked/completed) rather than any non-idle status, or is pulling to the tagged pane on active what you want as well? No strong view here, it's a semantics call.
fyi the branch is 5 commits behind master and conflicting right now.
Summary
Why
Expose common actions and session navigation from the Dock without requiring the app window to be frontmost.
Mostly remove the need in menu bar extra #140
Screenshot