mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-18 04:41:56 +00:00
fix(kanban): /kanban slash command emits argparse garbage instead of help
Closes #21794. `/kanban`, `/kanban help`, `/kanban --help`, and `/kanban <sub> -h` all returned broken output to the gateway and interactive CLI. Three underlying bugs in `hermes_cli.kanban.run_slash`: 1. argparse writes help to **stdout** but `run_slash` only captured stderr at parse time, so `-h` text was silently swallowed and replaced with the `(usage error: 0)` sentinel. 2. The wrapping parser used `prog="/"` and routed via a synthetic "_top → kanban" subparser, producing `usage: / kanban …` (stray space) and `usage: /kanban kanban …` (doubled token) in error text. 3. Bare `/kanban` and `/kanban help` dumped argparse's full ~3KB usage tree, which reads as visual garbage in a chat bubble. Fix: drive the kanban_parser directly (no double-wrap), rewrite prog strings on every leaf subparser, capture stdout AND stderr around parse_args, distinguish SystemExit(0) (help — return captured stdout) from SystemExit(2) (error — return single-line ⚠-prefixed message), and add an explicit chat-friendly short-help block returned for bare invocation and the help aliases (`help`, `--help`, `-h`, `?`). Added 5 regression tests covering bare invocation, every help alias, subcommand help, unknown action, and missing required arg. Affects every chat platform via gateway/run.py::_handle_kanban_command and the interactive CLI via cli.py::_handle_kanban_command. Co-Authored-By: Nagatha (Claude Opus 4.7) <noreply@anthropic.com>
This commit is contained in:
parent
3d2bfc502e
commit
d1fc748def
2 changed files with 118 additions and 23 deletions
|
|
@ -331,13 +331,64 @@ def test_run_slash_specify_end_to_end(kanban_home, monkeypatch):
|
|||
|
||||
|
||||
def test_run_slash_specify_help_is_reachable(kanban_home):
|
||||
"""`--help` on a subcommand is handled by argparse itself — it prints
|
||||
to the process stdout and raises SystemExit before run_slash's output
|
||||
redirection is installed, so the returned string is the usage-error
|
||||
sentinel. All we're asserting here is that the subcommand is
|
||||
registered (no "unknown action" error) — the shape of the help text
|
||||
is covered by the direct argparse tests in test_kanban_specify.py."""
|
||||
"""`-h`/`--help` on a subcommand returns the actual help text — see
|
||||
issue #21794. argparse writes help to stdout and exits 0; run_slash
|
||||
must capture both streams and treat exit 0 as success, not error."""
|
||||
out = kc.run_slash("specify --help")
|
||||
# Either the usage-error sentinel (stdout swallowed by argparse) or
|
||||
# a real help rendering — both mean the subcommand exists.
|
||||
assert "usage error" in out.lower() or "specify" in out.lower()
|
||||
assert "specify" in out.lower()
|
||||
# Help dump should NOT come back wrapped as a usage error.
|
||||
assert not out.startswith("⚠")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# /kanban help / no-args / unknown-action UX (issue #21794)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_run_slash_bare_returns_curated_help(kanban_home):
|
||||
"""Bare `/kanban` returns the curated short-help block — not a 5KB
|
||||
argparse usage dump."""
|
||||
out = kc.run_slash("")
|
||||
assert "/kanban" in out
|
||||
assert "list" in out
|
||||
assert "show" in out
|
||||
# Sanity: should be a chat-friendly size, not the raw usage tree.
|
||||
assert len(out) < 2000
|
||||
# Shouldn't surface argparse's usage-error sentinel.
|
||||
assert "usage error" not in out.lower()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("alias", ["help", "--help", "-h", "?"])
|
||||
def test_run_slash_help_aliases_match_bare(kanban_home, alias):
|
||||
"""Every documented help alias produces the same curated output."""
|
||||
bare = kc.run_slash("")
|
||||
out = kc.run_slash(alias)
|
||||
assert out == bare
|
||||
|
||||
|
||||
def test_run_slash_subcommand_help_returns_help_text(kanban_home):
|
||||
"""`/kanban show -h` returns the actual subcommand help, not a
|
||||
fake `(usage error: 0)` sentinel."""
|
||||
out = kc.run_slash("show -h")
|
||||
assert "task_id" in out
|
||||
assert "/kanban show" in out
|
||||
assert not out.startswith("⚠")
|
||||
|
||||
|
||||
def test_run_slash_unknown_action_friendly_error(kanban_home):
|
||||
"""Unknown subcommand surfaces a single-line usage error prefixed
|
||||
with our marker — no `(usage error: 2)` wrapping, no doubled
|
||||
`kanban kanban` prog string."""
|
||||
out = kc.run_slash("frobnicate")
|
||||
assert "/kanban" in out
|
||||
assert "frobnicate" in out
|
||||
assert "/kanban-wrap" not in out
|
||||
assert "/kanban kanban" not in out
|
||||
assert "(usage error: " not in out
|
||||
|
||||
|
||||
def test_run_slash_missing_required_arg_friendly_error(kanban_home):
|
||||
"""Missing positional argument shows the subcommand-scoped usage
|
||||
line, not the top-level kanban tree."""
|
||||
out = kc.run_slash("show")
|
||||
assert "/kanban show" in out
|
||||
assert "task_id" in out
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue