Files
hermes-agent/tests/hermes_cli
Brooklyn Nicholson 036c577c86 fix(desktop): surface staged skill-write review on the desktop and TUI
With skills.write_approval on, every skill write is staged to the
file-backed pending store, but no non-CLI surface could review it:
the desktop resolver marked the whole /skills family as the sidebar's
(desktop="settings") and discarded the subcommand token, and
tui_gateway command.dispatch had no route for /skills or /memory —
a failed slash worker turned both into the routing refusal, so staged
writes accumulated silently (#98330, #123315, #118812).

- hermes_cli/commands.py: new CommandDef.desktop_subcommands field;
  /skills declares its write-approval review slice
  (pending/approve/reject/diff/approval) and drops desktop="settings".
  command_desktop_meta serializes the allowlist (empty tuple = deny
  all); gateway contract regenerated.
- apps/desktop: the resolver threads the typed arg —
  desktopSubcommandAllowlist, an exec gate
  (desktopSubcommandUnavailableMessage) that renders an actionable
  refusal for hub mutations instead of forwarding them, completion
  filtering so the popover never suggests a dead end, and the
  isDesktopSlashCommand(name, arg) threading at the runExec gate.
  An explicit /skills spec keeps a current Desktop able to review
  staged writes even against an older backend catalog.
- tui_gateway command.dispatch: _cmd_skills answers only the
  registry-declared review slice under _session_home_scope (an
  unlisted subcommand keeps the 4018 routing refusal); _cmd_memory
  routes the shared handler with the live agent's store or a fresh
  on-disk one and a profile-scoped config setter. Gate-off still
  answers while staged writes exist (gateway parity, never stranded).
- tools/write_approval: _staged()'s review hint is surface-aware —
  slash-capable surfaces (CLI/TUI/desktop/chat gateway) keep
  "<command> pending"; headless contexts (cron, kanban, api_server,
  webhook delivery) get the pending directory path instead of a
  command nobody can deliver.

Batch skill writes also rendered "(batch on ...)" for /skills diff —
skill_pending_diff had no action='batch' case; ops now diff in order
against what earlier ops of the same batch left (finn763's #123861).

Supersedes #98794 (registry-driven desktop_subcommands + resolver
allowlist), #105773, #118821 (command.dispatch handlers + arg
threading), #123861 (batch diff renderer). #107799 is superseded by
the same subcommand-aware resolution.

Co-authored-by: foma-agent <foma@bokonon.ai>
Co-authored-by: Jason Havenaar <35441875+jasonHav@users.noreply.github.com>
Co-authored-by: finn763 <165816600+finn763@users.noreply.github.com>
Co-authored-by: chelsealong <chelsealong@126.com>
2026-09-30 23:05:43 -05:00
..