Skip to content

fix(cli): tokenized dashboard cmdline matcher — detect global flags before the subcommand#44165

Open
AIalliAI wants to merge 1 commit into
NousResearch:mainfrom
AIalliAI:fix/44035-dashboard-pid-profile-flag
Open

fix(cli): tokenized dashboard cmdline matcher — detect global flags before the subcommand#44165
AIalliAI wants to merge 1 commit into
NousResearch:mainfrom
AIalliAI:fix/44035-dashboard-pid-profile-flag

Conversation

@AIalliAI

Copy link
Copy Markdown
Contributor

Problem

_find_stale_dashboard_pids() matches fixed substrings ("hermes dashboard", "hermes_cli.main dashboard", "hermes_cli/main.py dashboard"), so any invocation with global options between the entrypoint and the subcommand —

python -m hermes_cli.main --profile work dashboard --host 0.0.0.0 --port 9119 --no-open --skip-build

— is invisible to hermes dashboard --status, hermes dashboard --stop, and the post-update stale-backend cleanup. After hermes update, a profile-scoped dashboard keeps serving the old Python backend against the freshly-built JS bundle.

Fix

Replace the substring patterns with a tokenized matcher (_is_dashboard_cmdline):

  1. Find the hermes entrypoint token — hermes/hermes.exe basename, hermes_cli.main (after -m), or a hermes_cli/main.py script path.
  2. Walk forward over known top-level flags until the first positional; match only if it is exactly dashboard.

Flag arity (does --profile consume a value? is --tui boolean?) is introspected from the real top-level parser plus PRE_ARGPARSE_INHERITED_FLAGS — the same approach hermes_cli.relaunch uses for its inherited-flag table — so the matcher can't drift out of sync as global options are added.

Unknown flags and free-text arguments bail out. This matters because the scan feeds a SIGTERM/SIGKILL pass: ps output does not preserve shell quoting, so a looser "both words appear" match would kill hermes -z "summarize my dashboard" mid-session during hermes update. The matcher is strictly tighter than the old patterns on this front — the old "hermes dashboard" substring already false-matched cmdlines like hermes -z fix hermes dashboard, which now stays alive (covered by a regression test).

Relation to #44048: alternative implementation. That PR's helper accepts any cmdline where an entrypoint substring appears anywhere (including e.g. paths containing .hermes/) and dashboard appears as a whitespace-delimited word anywhere — which false-positive-kills oneshot/chat sessions that mention "dashboard", since real ps output strips the quotes its guard relies on. Happy to converge the two PRs either way.

Both detection consumers are covered (--status/--stop via _report_dashboard_status/_kill_stale_dashboard_processes, update cleanup via the same kill helper), Windows wmic and POSIX ps branches share the matcher.

Tests

  • 9 new regression tests: the exact [Bug]: dashboard status/update miss running dashboards when --profile appears before the subcommand #44035 LaunchAgent shape, -p, --profile=, boolean flags, script-path form, plus negative cases (other subcommands, prompts mentioning "dashboard", profile literally named dashboard, unknown flags).
  • tests/hermes_cli/test_update_stale_dashboard.py + test_dashboard_lifecycle_flags.py: 41/41 pass.
  • Full tests/hermes_cli/ suite: failure set identical to origin/main baseline on the same machine (161 pre-existing environment failures, zero new), 9 more tests passing.

Fixes #44035

🤖 Generated with Claude Code

…the subcommand

The stale-dashboard scan in _find_stale_dashboard_pids() matched fixed
substrings ("hermes dashboard", "hermes_cli.main dashboard", ...), so any
invocation with global options between the entrypoint and the subcommand —
e.g. `python -m hermes_cli.main --profile work dashboard --port 9119` —
was invisible to `hermes dashboard --status`, `--stop`, and the
post-update stale-backend cleanup. After `hermes update`, a
profile-scoped dashboard kept serving the old Python backend against the
new JS bundle.

Replace the substring patterns with a tokenized matcher that finds the
hermes entrypoint (binary, -m module, or script path) and then walks
known top-level flags — introspected from the real parser, the same way
hermes_cli.relaunch builds its inherited-flag table — until it hits the
subcommand. Unknown flags and free-text arguments bail out, so cmdlines
that merely mention "dashboard" (`hermes -z "fix my dashboard"`, which
the old substring match would have killed) are never matched.

Fixes NousResearch#44035

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels Jun 11, 2026
@liuhao1024

Copy link
Copy Markdown
Contributor

Code review: clean

The tokenized cmdline matcher is a solid improvement over substring matching. Verified:

  1. _dashboard_global_flag_arity() introspects the real top-level parser — flags won'''t drift out of sync with the CLI.
  2. The =-form flag handling (--profile=work) correctly skips the value token by only incrementing i += 1.
  3. Unknown flags bail out rather than guessing arity — prevents false positives on future flags.
  4. The test suite covers all edge cases: profile flag before subcommand, short flag, equals form, boolean flag, script path form, oneshot prompt mentioning dashboard (no false positive), profile value named dashboard (no false positive), and unknown flag (no false positive).

No issues found.

@AIalliAI

Copy link
Copy Markdown
Contributor Author

Requesting maintainer review — this is ready to land from my side. Standalone fork CI is pending first-run approval here; the rollup branch in #44061 carrying this session's batch is fully green on upstream CI (all test shards, typecheck, e2e).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: dashboard status/update miss running dashboards when --profile appears before the subcommand

3 participants