fix(sessions): stop a /skill's own text becoming the session title - #71843
Merged
Conversation
A /skill invocation expands into a message that embeds the whole skill body. Anything that summarizes a user turn from its raw content reads the skill's prose as if the user had written it. describe_skill_invocation() sits next to the existing extractor and reuses its markers, returning `/work — fix the title leak` for an invocation with an instruction and `/work` for a bare one. It also exports the SQL LIKE pattern and excerpt-joint sentinel that listing queries need to recognize scaffolding before a row reaches Python.
generate_title() sent the first 500 characters of the user turn to the auxiliary model. On a /skill invocation those characters are the skill's own opening prose, so the session got named after the skill instead of the request — /work sessions came back as "Isolated Git Worktree Setup". Route the turn through describe_skill_invocation() first, so the titler sees what the user typed. Also keep only the first line of the response: a model that ignores "return ONLY the title" and answers the prompt would otherwise have a shell transcript stored as the title, truncated mid-command.
`preview` is the head of the first user message and the title fallback on every surface — sidebar rows, pickers, exports, the desktop's sessionTitle(). An untitled /skill session therefore read `[IMPORTANT: The user has invoked the "work" skill, indicatin...` wherever it appeared. A scaffolded row now selects a wide enough excerpt to reach the typed instruction (head + tail spliced for a long body) and shapes it through describe_skill_invocation(). Because previews are computed on read, existing sessions are corrected without a migration. The six copies of the preview subquery and four copies of its shaping collapse into one expression and one helper along the way, and the /rewind picker gets the same treatment.
Previews correct themselves on read, but a title already written to the DB stays wrong. This regenerates those titles from what the user actually typed, dry-run by default. Two guards, both hit on a real store: a candidate that isn't title-shaped is rejected rather than replacing a serviceable title with command output, and a unique-title collision dedupes through the lineage the way the live auto-titler does instead of leaving the leaked title in place.
Contributor
૮ >ﻌ< ა ci reviewran on 16042b0 ℹ️ InfoDesktop E2E visual evidence · View test artifacts · View job1 visual diff. inline evidence upload failed. Failed to upload diff-665a0833239e-onboarding-overlay-diff.png with gh image (exit code 1): Error uploading /home/runner/work/_temp/e2e-evidence/diff-665a0833239e-onboarding-overlay-diff.png: step 0 (get upload token): uploadToken not found on repo page — do you have write access to NousResearch/hermes-agent? (or, if NousResearch enforces SAML SSO, authorize at https://github.com/orgs/NousResearch/sso) |
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
…e-leak fix(sessions): stop a /skill's own text becoming the session title
33hodl
pushed a commit
to 33hodl/hermes-agent
that referenced
this pull request
Aug 12, 2026
…e-leak fix(sessions): stop a /skill's own text becoming the session title
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A
/skillinvocation expands into a message that embeds the whole skill body before it reaches the agent. Two surfaces summarize a user turn from that raw content, and both were reading the skill's prose as if the user had written it.Titles.
generate_title()sent the first 500 characters of the turn to the auxiliary model — on a/skillturn, that's the skill's opening lines./worksessions came back titled "Isolated Git Worktree Setup" and "Timeline idle optimization in worktree" instead of describing the actual request.Previews.
previewis the head of the first user message, and it's the title fallback on every surface: sidebar rows, pickers, exports, the desktop'ssessionTitle(). An untitled skill session read[IMPORTANT: The user has invoked the "work" skill, indicatin...wherever it appeared.describe_skill_invocation()sits next to the existingextract_user_instruction_from_skill_message()and reuses its markers, recovering/work — fix the title leakfrom an expanded turn. The titler and the preview queries both route through it, as does the/rewindpicker.Previews are computed on read, so existing sessions correct themselves with no migration. A title already written to the DB doesn't, so
hermes sessions retitle-skillsregenerates those — dry-run by default. Two guards earned on a real store: a candidate that isn't title-shaped is rejected rather than replacing a serviceable title with echoed command output, and a unique-title collision dedupes through the lineage the way the live auto-titler does.While in there, the six copies of the preview subquery and four copies of its shaping collapse into one expression and one helper.
Verified against a copy of a real 1274-session store: 12 affected sessions, previews corrected on read,
--applyre-titled 11 and correctly declined the 12th.