Skip to content

fix(title): do not persist generic fallback titles#1157

Closed
franksong2702 wants to merge 1 commit intonesquena:masterfrom
franksong2702:franksong2702/title-generic-fallback-skip
Closed

fix(title): do not persist generic fallback titles#1157
franksong2702 wants to merge 1 commit intonesquena:masterfrom
franksong2702:franksong2702/title-generic-fallback-skip

Conversation

@franksong2702
Copy link
Copy Markdown
Contributor

Summary

Fixes #1155.

When title generation falls back after an auxiliary LLM failure, the local fallback can produce the generic placeholder Conversation topic. Persisting that as the generated title is worse than keeping the existing provisional title because it adds no useful session-list signal.

This PR keeps the existing title when the local fallback is generic, while preserving the underlying title_status diagnostic reason such as llm_error_aux.

Changes

  • Adds a small generic-fallback guard for low-information local title labels.
  • Skips persisting Conversation topic as s.title.
  • Avoids setting llm_title_generated = True when no meaningful title was generated.
  • Keeps the existing provisional title and emits title_status: skipped with the original LLM failure reason.
  • Adds regression coverage for the non-Latin / low-confidence fallback path.

Why this layer

The provider failure is still useful diagnostic information, but the fallback persistence decision lives in api/streaming.py where the title update is committed. This avoids changing provider routing, title SSE rendering, or session-list display behavior.

Verification

  • python -m pytest tests/test_title_aux_routing.py tests/test_title_sanitization.py tests/test_1058_adaptive_title_refresh.py tests/test_issues_853_857.py -q
  • python -m py_compile api/streaming.py
  • git diff --check

@nesquena-hermes
Copy link
Copy Markdown
Collaborator

Nice fix, @franksong2702! The layering decision (guard in api/streaming.py at persistence time, not in the provider or SSE rendering layers) is well reasoned.

The core change — skipping s.title = fallback_value and llm_title_generated = True when the local fallback returns a generic placeholder — is exactly right. Keeping the provisional first-message title is always better than overwriting it with Conversation topic, which carries zero session-list signal.

The title_status: skipped diagnostic with the original LLM failure reason preserved is a good touch — it means the failure is still observable in logs without leaving visible noise for the user.

The regression tests covering the non-Latin / low-confidence fallback path close the gap left after the reasoning-model hardening in #1026 / #1031. Fixes #1155.

nesquena-hermes added a commit that referenced this pull request Apr 27, 2026
Merged as v0.50.227. 2634 tests passing, browser QA 21/21 (desktop + mobile). Full attribution below.

Thanks to all 12 contributors:
@jundev0001 (#1138), @franksong2702 (#1142, #1157, #1162), @dso2ng (#1143), @bergeouss (#1145, #1146, #1156, #1159), @jasonjcwu (#1149), @ccqqlo (#1161), @frap129 (#1165)

Two fixes applied during integration and two more by the independent reviewer (@nesquena):
- messages.js: per-turn cost delta capture order (#1159)
- workspace.py: symlink target blocked-roots check + HOME sanity guard (#1149, #1165)
- panels.js: cron unread counter bookkeeping (in-loop increment bug)
- tests/test_symlink_cycle_detection.py: register workspace before session/new
@nesquena-hermes
Copy link
Copy Markdown
Collaborator

Merged as v0.50.227 via batch PR #1168. Thank you @franksong2702! 🎉

JKJameson pushed a commit to JKJameson/hermes-webui that referenced this pull request Apr 29, 2026
Merged as v0.50.227. 2634 tests passing, browser QA 21/21 (desktop + mobile). Full attribution below.

Thanks to all 12 contributors:
@jundev0001 (nesquena#1138), @franksong2702 (nesquena#1142, nesquena#1157, nesquena#1162), @dso2ng (nesquena#1143), @bergeouss (nesquena#1145, nesquena#1146, nesquena#1156, nesquena#1159), @jasonjcwu (nesquena#1149), @ccqqlo (nesquena#1161), @frap129 (nesquena#1165)

Two fixes applied during integration and two more by the independent reviewer (@nesquena):
- messages.js: per-turn cost delta capture order (nesquena#1159)
- workspace.py: symlink target blocked-roots check + HOME sanity guard (nesquena#1149, nesquena#1165)
- panels.js: cron unread counter bookkeeping (in-loop increment bug)
- tests/test_symlink_cycle_detection.py: register workspace before session/new
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(title): do not persist generic Conversation topic fallback

2 participants