Files
hermes-agent/tests/hermes_cli/test_kanban_worker_spawn_toolsets.py
T
Teknium 6b81590c55 test: prune low-value tests suite-wide (wave 1) — 46,820 → 28,106 test functions
Systematic prune per AGENTS.md test policy, one pass over every major
test tree (gateway, hermes_cli, tools, agent, run_agent, plugins, cli,
cron, tui_gateway, honcho/openviking, root-level):

- DELETE: source-reading tests (read_text/getsource on prod files),
  change-detector tests (exact catalog counts, model-name snapshots,
  config version literals), mock-echo tests (assert a mock returns what
  it was told), assertion-free/trivial tests, near-duplicate
  parametrizations (boundaries + one representative kept), async/sync
  twin duplicates, cosmetic within-file variations.
- KEEP (mandatory): security/redaction/approval guards, message-role
  alternation invariants, prompt-caching/deterministic-call-id
  invariants, issue-number regression tests (deduped), E2E tests.
- 6 test files deleted outright (script-style/no-assert or fully
  redundant); conftest.py, fakes/, fixtures/ untouched.
- tests/acp/conftest.py added: autouse fixture stubs the live
  models.dev/GitHub/Copilot/Anthropic inventory fetches that ACP server
  tests performed on every session create — test_server.py 147s → 3.4s,
  and the tests are now genuinely hermetic.
- Sleep-based slowness shrunk where safe (codex_ttfb_watchdog,
  compression_concurrent_fork, etc.); no wall-clock assertion tightened.

Verification: full hermetic suite via scripts/run_tests.sh —
2439 files, 31,130 tests passed, 0 failed, 0 flaky retries, 315s wall
(baseline: 583s wall, 13,564s subprocess CPU).
2026-07-29 13:10:23 -07:00

164 lines
5.1 KiB
Python

from __future__ import annotations
import subprocess
def _make_task(kb, *, assignee: str):
return kb.Task(
id="t_spawn_tools",
title="spawn tools",
body=None,
assignee=assignee,
status="running",
priority=0,
created_by="test",
created_at=1,
started_at=None,
completed_at=None,
workspace_kind="dir",
workspace_path=None,
claim_lock="lock",
claim_expires=None,
tenant=None,
current_run_id=7,
)
def test_default_spawn_pins_assignee_profile_cli_toolsets(monkeypatch, tmp_path):
"""Manual profile assignment should keep that profile's CLI tools.
Regression guard for dispatcher-spawned workers that boot with
HERMES_KANBAN_TASK: the worker must not collapse to only kanban lifecycle
tools when the assigned profile's top-level ``toolsets`` is the default
composite. The spawned CLI gets an explicit --toolsets pin resolved from
platform_toolsets.cli; model_tools appends task-scoped kanban tools later.
"""
root = tmp_path / ".hermes"
profile = root / "profiles" / "elias"
profile.mkdir(parents=True)
profile.joinpath("config.yaml").write_text(
"""
platform_toolsets:
cli:
- clarify
- code_execution
- delegation
- file
- memory
- session_search
- skills
- terminal
- web
toolsets:
- hermes-cli
agent:
disabled_toolsets: []
""".lstrip(),
encoding="utf-8",
)
root.joinpath("config.yaml").write_text("toolsets:\n - kanban\n", encoding="utf-8")
monkeypatch.setenv("HERMES_HOME", str(root))
from hermes_cli import kanban_db as kb
monkeypatch.setattr(kb, "_resolve_hermes_argv", lambda: ["hermes"])
captured = {}
class FakeProc:
pid = 4242
def fake_popen(cmd, *args, **kwargs):
captured["cmd"] = list(cmd)
captured["env"] = dict(kwargs.get("env") or {})
captured["cwd"] = kwargs.get("cwd")
return FakeProc()
monkeypatch.setattr(subprocess, "Popen", fake_popen)
workspace = tmp_path / "workspace"
workspace.mkdir()
pid = kb._default_spawn(_make_task(kb, assignee="elias"), str(workspace))
assert pid == 4242
assert captured["env"]["HERMES_HOME"] == str(profile)
assert captured["env"]["HERMES_KANBAN_TASK"] == "t_spawn_tools"
assert "--toolsets" in captured["cmd"]
pinned = captured["cmd"][captured["cmd"].index("--toolsets") + 1].split(",")
for required in ("terminal", "web", "file", "skills", "code_execution", "delegation"):
assert required in pinned
def test_default_spawn_model_override_survives_real_cli_parse(monkeypatch, tmp_path):
"""The dispatcher's pre-``chat`` model flag must reach ``args.model``.
This is an integration contract between Kanban's worker argv builder and
the real CLI parser. A parser default once erased the explicit override,
silently sending the worker to its profile default or fallback instead.
"""
root = tmp_path / ".hermes"
(root / "profiles" / "elias").mkdir(parents=True)
root.joinpath("config.yaml").write_text("{}\n", encoding="utf-8")
monkeypatch.setenv("HERMES_HOME", str(root))
from hermes_cli import kanban_db as kb
from hermes_cli._parser import build_top_level_parser
monkeypatch.setattr(kb, "_resolve_hermes_argv", lambda: ["hermes"])
captured = {}
class FakeProc:
pid = 4244
def fake_popen(cmd, *args, **kwargs):
captured["cmd"] = list(cmd)
return FakeProc()
monkeypatch.setattr(subprocess, "Popen", fake_popen)
workspace = tmp_path / "workspace"
workspace.mkdir()
task = _make_task(kb, assignee="elias")
task.model_override = "gpt-5.6-sol"
kb._default_spawn(task, str(workspace))
parser, _subparsers, _chat_parser = build_top_level_parser()
# Profile selection is attached by the outer CLI bootstrap rather than
# build_top_level_parser(); remove that already-validated prefix and parse
# the worker flags/subcommand through the real shared parser.
assert captured["cmd"][1:3] == ["-p", "elias"]
args = parser.parse_args(captured["cmd"][3:])
assert args.command == "chat"
assert args.model == "gpt-5.6-sol"
assert args.query == "work kanban task t_spawn_tools"
def test_resolve_worker_cli_toolsets_uses_profile_home_not_parent_config(monkeypatch, tmp_path):
root = tmp_path / ".hermes"
profile = root / "profiles" / "elias"
profile.mkdir(parents=True)
root.joinpath("config.yaml").write_text("platform_toolsets:\n cli:\n - kanban\n", encoding="utf-8")
profile.joinpath("config.yaml").write_text(
"""
platform_toolsets:
cli:
- terminal
- web
toolsets:
- hermes-cli
""".lstrip(),
encoding="utf-8",
)
monkeypatch.setenv("HERMES_HOME", str(root))
from hermes_cli import kanban_db as kb
resolved = kb._resolve_worker_cli_toolsets(str(profile))
assert resolved is not None
assert "terminal" in resolved
assert "web" in resolved
assert "kanban" in resolved # recovered worker lifecycle surface
assert resolved != ["kanban"]