`hermes chat -q`/`--oneshot`/`-Q` and `hermes -z` (both set HERMES_SINGLE_QUERY_SESSION=1)
persisted their session as `cli` — and, before the first pass, as the inherited
`tui`/`desktop` transport label — so finite automation runs sat in the TUI, Desktop and
dashboard session pickers next to real conversations (#112550).
- run_agent._session_source_for_agent: a single-query run whose source is empty (or an
inherited UI transport label without an explicit --source) resolves to `oneshot`; the
platform gate keeps delegate children (`subagent`) untouched; an explicit `--source`
(HERMES_SESSION_SOURCE_EXPLICIT=1 from main.py) still wins.
- hermes_state_sessions.INTERNAL_LISTING_SOURCES = (kanban, tool, oneshot) replaces the
three copied `["kanban", "tool"]` literals (tui_gateway session.list, console
`sessions list`/`stats`, in-chat /sessions), and the Desktop project tree / sidebar
recents and the dashboard automation set exclude `oneshot` too.
- `hermes -c` / `--resume latest` still chain on the previous one-shot (PR #105957's
documented flow): the CLI MRU lookup matches the cli family {cli, oneshot} and
search_sessions accepts several sources; one-shots keep stamping their launch cwd so the
workspace-scoped lookup keeps working.
- Compression child: the rotated child is published with the PARENT ROW's persisted source
instead of bare agent.platform, so a `--source tool` / `oneshot` / inherited `kanban`
session does not degrade to a picker-visible `cli` row after compaction.
- Docs: sessions source table (+ oneshot/kanban/tool rows, compression note) and the
`--source` flag reference (explicit flag always stored as given).
_session_source_for_agent now drops an inherited tui/desktop
HERMES_SESSION_SOURCE for finite chats, but main.py exports the
documented --source flag through the very same variable, so
'hermes chat -q --source tui' was silently relabelled 'cli' with no way
to opt out. main.py marks an explicit flag with
HERMES_SESSION_SOURCE_EXPLICIT=1 and the resolver keeps the label when
that marker is set; no internal launcher passes --source tui/desktop, so
inherited transport labels are still dropped.
A finite `hermes chat -q` (or `hermes -z` one-shot) launched from inside a TUI
or Desktop session inherits HERMES_SESSION_SOURCE=tui/desktop — the terminal
tool bridges the session env into child processes — and
`_session_source_for_agent` honoured that inherited transport label over the
child's own platform. The row was persisted as a `tui` chat, so it appeared in
the TUI/WebUI session pickers as a resumable conversation and `hermes -c` in
the TUI could continue it.
The resolver now drops an inherited UI-transport source (`tui`, `desktop`) when
the finite-chat marker HERMES_SINGLE_QUERY_SESSION=1 is set, falling back to the
child's platform (`cli`). Automation sources (kanban, tool, cron, a2a, ...) are
still inherited on purpose — kanban dispatch relies on it. `run_oneshot` sets
the same marker as `hermes chat -q` already does.
Deliberately NOT a new `oneshot` source and NOT a forced `tool` source: `tool`
is the documented opt-in (`--source tool`) for integrations that must stay out
of session lists, `hermes -c` resolves the latest session by source=cli, and
every picker (TUI gateway deny list, dashboard automation category,
session_search, `hermes sessions list`) already filters on the existing
sources. Whether plain one-shot runs should be hidden by default is a product
call left to the maintainer (see PR body).
Part of #112550
Co-authored-by: KoNit-K <124019182+KoNit-K@users.noreply.github.com>
Co-authored-by: fangliquan <fangliquan@qq.com>
`scripts/run_tests.sh tests/<dir>/` is how a change gets its regression
coverage run, so a test filed under the wrong directory is a test nobody
runs when that code changes. Two kinds of drift had accumulated.
Parallel directories for one source package, folded into the mirror:
tests/acp -> tests/acp_adapter (its __init__/conftest move with it)
tests/cli -> tests/hermes_cli (prompt_toolkit fixture merged into
hermes_cli/conftest.py)
tests/run_agent -> tests/agent (backoff fixture becomes
agent/conftest.py)
tests/relay -> tests/gateway/relay
tests/state -> tests/hermes_state
246 loose files at tests/ root, routed by the package they import/patch:
hermes_cli, hermes_state, agent, gateway, tools, plugins, tui_gateway, cron.
Installer and desktop-update script tests go to tests/scripts/{install,
desktop_update}/. 43 tests of root-level modules (batch_runner, utils,
hermes_constants, packaging) stay at the root.
Filenames drop their issue numbers (95 files: test_89315_x.py -> test_x.py);
the number stays in the module docstring where it has context.
Collisions: test_cli_skin_integration.py existed in both tests/ and tests/cli
with different subsets — merged into one (10 tests, all kept);
run_agent/test_pre_compress_memory_context.py -> agent/..._handoff.py;
tests/test_account_usage.py -> agent/test_account_usage_fetch.py;
tests/test_web_server.py -> hermes_cli/test_web_server_ws_ping.py.
Deleted: test_minisweagent_path.py (empty since PR #2804),
test_model_picker_scroll.py (tested a private copy of the logic, imported
nothing), test_process_loop_event_loop_warning.py (asserted asyncio behaviour,
imported nothing from Hermes).
Repo-root path arithmetic (Path(__file__).parents[N], dirname chains) is
bumped for the 202 files that changed depth and verified by evaluating every
such expression against the new location. classify_changes' desktop-updater
lane prefix, tests-os.yml's ignore glob and every in-tree path comment follow
the moves. tests/test_tests_tree_layout.py keeps the tree from drifting back.