The dashboard console previously ran under a 'hosted' context that
blocked most commands (auth add, config set model.*, mcp add --command,
cron --script, ...) behind an allowlist + line-policy layer. With the
full Hermes CLI now built into the dashboard, that policy layer is
redundant gatekeeping: the console gets the same command surface
everywhere.
Removed:
- ConsoleContext/contexts plumbing on ConsoleCommand + engine
- EXPECTED_HOSTED_PATHS allowlist + _mark_hosted
- _enforce_hosted_line_policy + HOSTED_CONFIG_* allow/block tables
- _dashboard_console_context() and the context field on the ready frame
- hosted-context tests; context badge in HermesConsoleModal
Kept (mechanical, not policy): shell-syntax rejection, the
interactive/server command blocks (gateway, dashboard, mcp serve, ...),
mutating-command confirmations, output caps, and command timeouts.
Addresses two non-blocking review notes on the Hermes Console PR:
- console_engine: the four _*_summaries helpers import a subcommand module
and build a throwaway argparse tree purely to extract help summaries. The
dashboard opens a fresh HermesConsoleEngine per /api/console connection, so
every reconnect re-imported + re-parsed the whole CLI surface. The surface
is process-static, so memoize with functools.lru_cache — callers only read
the returned map.
- web_server: console commands run in a worker thread via asyncio.to_thread.
On a 60s timeout asyncio.wait_for cancels the awaitable, but Python threads
aren't preemptible, so a stuck worker keeps running and would leak into the
shared default thread pool. Route console execution through a small
dedicated bounded ThreadPoolExecutor (max_workers=4) so a leaked worker is
capped and concurrent console execution is bounded regardless of reconnects.
Follow-up on top of @shannonsands' NS-574 Hermes Console.