Skip to content

fix(cli): collapse timeline markers and /skill invocations in the resume preview - #71950

Open
pierrenode wants to merge 1 commit into
NousResearch:mainfrom
pierrenode:fix/cli-resume-preview-system-marker-leak
Open

fix(cli): collapse timeline markers and /skill invocations in the resume preview#71950
pierrenode wants to merge 1 commit into
NousResearch:mainfrom
pierrenode:fix/cli-resume-preview-system-marker-leak

Conversation

@pierrenode

@pierrenode pierrenode commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

_display_resumed_history() (the CLI's "Previous Conversation" recap shown on /resume and hermes --resume) is a separate display projection from tui_gateway/server.py::_history_to_messages (the one desktop/TUI/web read). It special-cases the display_kind values it happens to know about, but two classes of bookkeeping/scaffolding rows fall through to the plain role=="user" branch and render as fake You: bubbles:

  1. Personality-change/clear markertui_gateway.server's _set_personality() writes a plain role=user "[System: ...]" row with no display_kind. _history_to_messages already hides it via _is_display_hidden_marker() (a role + "[System:" prefix check, independent of display_kind); the CLI's recap never picked up the same check.
  2. /skill invocations — persisted expanded (activation note plus the entire skill body). _history_to_messages already collapses this onto the invocation the user typed via describe_skill_invocation(); the CLI's recap showed up to 300 raw characters of the expanded body as if the user had written it.

This is the third time this general bug class has been closed without covering the CLI path — #68665 / #69861 fixed the duplicate-bubble symptom on desktop, and a same-day sibling commit widened _history_to_messages for "desktop, TUI, CLI, and web transcripts" even though that function is never on the CLI's hermes --resume code path.

Fix

  • Personality marker: same role == "user" + "[System:" prefix check as _is_display_hidden_marker(), added to _display_resumed_history()'s history loop. Positioned after the display_kind special cases (so model_switch's "◈ model changed" event line is unaffected) and before the plain role == "user" handling.
  • Skill invocations: describe_skill_invocation() (from agent.skill_commands, the same helper tui_gateway/server.py uses) is called on role=="user" content; a match renders as "◈ skill invoked: /work — fix the leak" instead of the expanded body, consistent with the existing model-switch / async-delegation event lines.

Deliberately not importing tui_gateway.server to reuse _is_display_hidden_marker directly — that module is not otherwise on the CLI's import graph and is a large gateway-oriented module. The duplicated prefix check is commented to point back at _is_display_hidden_marker so the two stay in sync if the marker wording/role ever changes.

Changes

  • hermes_cli/cli_agent_setup_mixin.py: skip role=="user" rows whose content starts with "[System:"; collapse role=="user" rows matching describe_skill_invocation() to an event line.
  • tests/cli/test_resume_display.py: 4 regression tests (personality-change marker, personality-cleared marker, skill invocation with instruction, bare skill invocation) — all assert the raw scaffolding never appears and the collapsed/hidden form renders correctly, while real conversation turns around them still render.

Validation

  • New tests pass; mutation-verify (each fix reverted independently) confirms all 4 fail with the exact bug's failure mode.
  • tests/cli/test_resume_display.py + tests/cli/test_cli_resume_command.py: 69/69 passed.
  • Broader tests/hermes_cli/ resume/agent-setup/skill subset: 312/313 passed — the one failure (test_session_platform_env_var) reproduces identically with both commits reverted (pre-existing test-order pollution via env-var leakage between tests, unrelated to this PR).
  • ruff check: clean.

@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have labels Jul 26, 2026
@pierrenode pierrenode changed the title fix(cli): hide personality-change bookkeeping marker from resume preview fix(cli): collapse timeline markers and /skill invocations in the resume preview Jul 28, 2026
@pierrenode
pierrenode force-pushed the fix/cli-resume-preview-system-marker-leak branch from a576677 to 54fd0cb Compare July 28, 2026 18:31
@teknium1

Copy link
Copy Markdown
Contributor

Thanks — this addresses a verified classic-CLI-only resume projection gap.

On current main, hermes_cli/cli_agent_setup_mixin.py:563-624 reads the raw resume display history and appends ordinary role == "user" content directly to the recap. That still exposes both kinds of scaffolding this PR targets. The canonical gateway behavior is already explicit: tui_gateway/server.py:6528 hides role=user [System: markers, and tui_gateway/server.py:6665-6672 projects expanded skill turns through describe_skill_invocation().

The proposed placement after the existing display_kind cases preserves timeline-event handling, while the new behavioral tests target the separate CLI renderer rather than source text.

GitHub currently reports this branch as conflicting. Salvage should resolve the local hunk by retaining main's auto_continue event handling at hermes_cli/cli_agent_setup_mixin.py:597-599, then placing the two new projections before the ordinary user branch at line 606.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 30, 2026
…ume preview

_display_resumed_history() (the CLI's "Previous Conversation" recap shown
on /resume and hermes --resume) is a separate display projection from
tui_gateway/server.py::_history_to_messages (the one desktop/TUI/web
read). It special-cases the display_kind values it happens to know
about, but two classes of bookkeeping/scaffolding rows fell through to
the plain role=="user" branch and rendered as fake You: bubbles:

1. Personality-change/clear marker — tui_gateway.server's
   _set_personality() writes a plain role=user "[System: ...]" row with
   no display_kind. _history_to_messages already hides it via
   _is_display_hidden_marker() (a role + "[System:" prefix check,
   independent of display_kind); the CLI's recap never picked up the
   same check.
2. /skill invocations — persisted expanded (activation note plus the
   entire skill body). _history_to_messages already collapses this onto
   the invocation the user typed via describe_skill_invocation(); the
   CLI's recap showed up to 300 raw characters of the expanded body as
   if the user had written it.

This is the third time this general bug class has been closed without
covering the CLI path — NousResearch#68665 / NousResearch#69861 fixed the duplicate-bubble
symptom on desktop, and a same-day sibling commit widened
_history_to_messages for "desktop, TUI, CLI, and web transcripts" even
though that function is never on the CLI's `hermes --resume` code path.

Fix:
- Personality marker: same role == "user" + "[System:" prefix check as
  _is_display_hidden_marker(), added to _display_resumed_history()'s
  history loop. Positioned after the display_kind special cases (so
  model_switch's "◈ model changed" event line is unaffected) and before
  the plain role == "user" handling.
- Skill invocations: describe_skill_invocation() (from
  agent.skill_commands, the same helper tui_gateway/server.py uses) is
  called on role=="user" content; a match renders as "◈ skill invoked:
  /work — fix the leak" instead of the expanded body, consistent with
  the existing model-switch / async-delegation event lines.

Deliberately not importing tui_gateway.server to reuse
_is_display_hidden_marker directly — that module is not otherwise on
the CLI's import graph and is a large gateway-oriented module. The
duplicated prefix check is commented to point back at
_is_display_hidden_marker so the two stay in sync if the marker
wording/role ever changes.

Tests: 4 regression tests (personality-change marker, personality-cleared
marker, skill invocation with instruction, bare skill invocation) in
tests/cli/test_resume_display.py — all assert the raw scaffolding never
appears and the collapsed/hidden form renders correctly, while real
conversation turns around them still render. Mutation-verified: each
fix reverted independently, confirmed both fail with the exact bug's
failure mode.
@pierrenode
pierrenode force-pushed the fix/cli-resume-preview-system-marker-leak branch from 54fd0cb to d076478 Compare August 11, 2026 23:29
@pierrenode

Copy link
Copy Markdown
Contributor Author

Rebased onto current `upstream/main` and squashed to a single commit.

`hermes_cli/cli_agent_setup_mixin.py` auto-merged cleanly. `tests/cli/test_resume_display.py` had one conflict: the pre-existing test this PR's diff shows as trailing context (`test_tool_messages_hidden`) has been renamed/rewritten upstream to `test_tool_only_message_skipped_by_default` with different content — kept upstream's current version untouched and inserted this PR's 4 new tests immediately before it. Verified the retained tail matches `upstream/main`'s file byte-for-byte from that point on.

Targeted suite (19 tests) passes, mutation-verified both fixes independently (disabling the `[System:` prefix check reproduces both personality-marker tests failing with the raw marker text visible in output; disabling the `describe_skill_invocation()` call reproduces both skill-invocation tests failing with the raw skill body visible). Broader sweep (`tests/cli/` filtered to resume/agent_setup/skill_commands, 59 tests, plus the dedicated `describe_skill_invocation` test file, 7 tests) passes clean. Ruff clean. Fresh competitor search found no PR touching this specific gap (the closest hits were unrelated `_display_resumed_history` symptoms — empty messages, hardcoded agent name, terminal escape sanitization).

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 sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants