T-0BET-commands-for-every-operation-and-save
State: planning/proposed · Impact: high · Complexity: small
Every button in Agent Manager calls its handler directly — save(), refresh(),
addPlugin() — with no matching palette entry, and mod+s only saves when focus sits
inside CodeMirror. This task makes every operation a registered command reachable from
mod+k, and makes mod+s save from anywhere on the page, so the milestone’s “every
operation is a command” success criterion holds for this experience.
| Location | Role today |
|---|---|
solutions/determined/experiences/agent-pants/app/plugins/register.ts#contributes.commands | Two commands only: agent-pants.open and agent-pants.new; no Save, Reload, Rename, Move, Delete, Convert kind, Dry run, Install, Build, Import, Rescan or filter/view-toggle commands |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/notes/[...path].vue#save | The header DButton’s @click="save()" and MdSurface’s @save="save()" both call this directly; no command wraps it |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/plugins/[...path].vue#save | Same direct-call pattern for a plugin’s own note |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/index.vue#save | Same pattern; also owns Rescan, Add plugin, Create marketplace and a kindFilter toggle-set, all @click-only |
packages/ts/app-frame/app/composables/useKeybindings.ts#useKeybindings | The one global keydown dispatcher; iterates useWindowCommands() and matches chords, but refuses to fire while the focused element is editable |
packages/ts/ui/app/utils/chords.ts#isEditableTarget | Treats INPUT/TEXTAREA/SELECT/contenteditable/role=textbox as text targets, so a command-level mod+s cannot reach a focused CodeMirror body |
packages/ts/obsidian-editor/src/plugins/editor.ts#editorSave | The editor’s own mod+s EditorCommand, enabled only when onSave is set; already calls the shared save from commands.ts |
packages/ts/obsidian-editor/src/commands.ts#obsidianKeymap | The base CodeMirror keymap also binds Mod-s to save, independent of the palette |
Proposed
Section titled “Proposed”A new useAgentManagerActions() composable in the experience is the single owner of
every operation a page or the palette can trigger: save, reload, rename, move, delete,
new-per-kind, rescan, import, and — once their surfaces exist — dry run, install, build,
convert kind, and the preview/related/publish toggles. register.ts’s
contributes.commands lists one entry per operation from the plan, each
context: 'agent-pants', calling into the composable. The three page components
register their active note’s handlers into the composable on mount instead of
implementing save/refresh locally; their header buttons call the same composable
functions the commands call, so the two cannot drift. mod+s is bound both as a
command-level keybinding (fires from any non-editable focus) and, unchanged, inside
CodeMirror (editorSave / obsidianKeymap) — both paths end at the composable’s
save().
Approach
Section titled “Approach”- Add
useAgentManagerActions(), a composable backed by shared reactive state (mirroringuseAgentPantsFocusResource’s shape), exposing register/unregister functions for the active page’s save, reload, rename, move, delete and rescan handlers, plus the wizard-opening new-per-kind actions that need no page context. Open decision: whether a command with no active page (nothing to save) reports itself disabled or no-ops — resolve against whatuseWindowCommands()already does for a targetless command. - Update
notes/[...path].vue,plugins/[...path].vueandindex.vueto register theirsave/refresh(and rename/move/delete where present) into the composable on mount and deregister on unmount; replace each@click="save()"etc. with a call into the composable so there is one implementation per operation. - Add the command list to
register.ts#contributes.commands: Save (mod+s), Reload, Rename, Move, Delete, New skill/command/agent/plugin/marketplace, Rescan, Import, Filter by kind — each wired to the composable or an existing navigation (seedUrl,/import). - Add Convert kind, Dry run, Install, Build, Next/previous preview target, and Toggle preview/related/publish view once their targets exist (see Dependencies) — same registration pattern, in this same file.
- Extend the Playwright walkthrough spec: assert the palette lists every
agent-pants.*command, and thatmod+swhile focus sits on a plain page element (not the editor) saves an open note.
| Area | Note |
|---|---|
solutions/determined/experiences/agent-pants/app/composables/useAgentManagerActions.ts | The single actions registry commands and buttons both call |
solutions/determined/experiences/agent-pants/app/plugins/register.ts | Add the full contributes.commands list and the mod+s keybinding |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/notes/[...path].vue | Register save/reload/rename/move/delete into the composable |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/plugins/[...path].vue | Same registration for the plugin note |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/index.vue | Same registration, plus Rescan/Add-plugin/kind-filter |
solutions/determined/products/agent-pants/tests/e2e/walkthrough.e2e.ts | Assert palette coverage and a non-editor mod+s save |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
register.ts#contributes.commandslists Save, Reload, Rename, Move, Delete, New skill/command/agent/plugin/marketplace, Rescan, Import and Filter by kind, eachcontext: 'agent-pants'. - AC-2: Opening the palette (
mod+k) on an Agent Manager screen and running “Save” performs the same write the header Save button performs. - AC-3: Pressing
mod+swith focus on a non-editor element on the note page saves the open note; pressing it with focus inside the CodeMirror body also saves. - AC-4:
grep -rn "function save" solutions/determined/experiences/agent-pants/app/pagesfinds no page-localsaveimplementation — each page callsuseAgentManagerActions(). - AC-5: The Playwright walkthrough spec asserts the full
agent-pants.*command list and the non-editormod+ssave.
Out of scope
Section titled “Out of scope”- Building the operations this task exposes as commands — rename, move, delete, install, build, import and rescan already work; this task only makes them reachable from the palette.
- The kind-conversion action itself (T-W8BH-kind-conversion-action); “Convert kind” is declared here against whatever surface that task ships.
- The preview, related and publish surfaces the toggle and next/previous-target commands act on (T-K1A2-preview-pane-per-entity-and-target, T-7UDE-related-files-tab, T-H3RG-publish-as-secondary-view).
Dependencies
Section titled “Dependencies”- T-W8BH-kind-conversion-action supplies the Convert kind command’s target.
- T-K1A2-preview-pane-per-entity-and-target supplies the target switcher the Next/previous preview target command steps through.
- T-7UDE-related-files-tab and T-H3RG-publish-as-secondary-view supply the views the Toggle preview/related/publish view commands switch to.
Discovery context
Section titled “Discovery context”From the user’s planning request of 2026-09-07 and the milestone success criterion
“every user-facing operation in the experience is a registered command reachable from
mod+k.” The assessment
solutions/agent-pants/docs/vault/design/workflow-and-ux-assessment.md documents the
CLI and rail drifting from what the core actually does; one actions owner keeps the
palette and the buttons from drifting from each other the same way.
Depends on
Section titled “Depends on”T-W8BH-kind-conversion-action, T-K1A2-preview-pane-per-entity-and-target, T-7UDE-related-files-tab, T-H3RG-publish-as-secondary-view