Conversation
The five-word gate in shouldGenerateThreadTitle counted the `/skill-name` token as an ordinary word, so a first message that invokes a skill almost always fell under the threshold and inference never ran. The thread kept a null title and the sidebar fell back to the raw prompt text. Exempt prompts carrying a command mention from the length gate, strip the command ranges out of the text handed to the model, and name the invoked commands in the metadata template so the title describes the work rather than the tool.
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.
Human comments
What was wrong
shouldGenerateThreadTitledecided eligibility fromcleanPromptText, which concatenatespart.textand ignorespart.mentions, so a/skill-namecommand mention was counted as an ordinary word against the five-word minimum. A first message that invokes a skill is short by design, so it fell under the threshold and title inference was skipped entirely — the provisioning transcript recordsreason: "too-short"withdurationMs: 0, the thread keepstitle = NULL, andgetThreadDisplayTitlefalls back to the raw prompt, leaving sidebar rows that read/sync-repo. The gate landed in6a4b7489e(2026-04-10), two months before command mentions existed in prompts (27361799e, #92), so it never made a decision about skills; this is an unhandled interaction, not a policy. Across a personal database of 1265 threads, 19 of 19 command-first prompts under five words were untitled.What changed
apps/server/src/services/threads/title-generation.tscollectInvokedPromptCommandsreadskind: "command"mentions off the input, deduplicated bytrigger + nameand kept in prompt order.shouldGenerateThreadTitleexempts a prompt carrying any command mention fromMIN_TITLE_GENERATION_WORDS. Invoking a skill is itself a statement of intent. Prompts without a command mention keep the existing five-word rule exactly.generateThreadMetadataWithOutcomenow hands the model the prompt body with the command ranges removed (viaremoveCommandMentionsFromPromptInput) plus the invoked command names as a separate variable, instead of the raw text. When stripping leaves nothing — a bare/weekly-report— it falls back to the clamped raw text so the model still has the command to title from.clampPromptTextso it applies to the stripped body as well as the fallback.deriveTitleFallbackis unchanged: a failed or skipped inference still degrades to today's behavior.packages/templates/src/templates/generate-thread-metadata.mdinvokedCommands?, rendered only when the prompt invokes something: it tells the model those names describe how the work is carried out, so the title should name the work they are applied to — and that when the prompt says nothing else, the title should describe what the command itself does. The template already asked for this ("it is the problem that should be the title, not the tools"); it simply never received the information.No wire changes, so
HOST_DAEMON_PROTOCOL_VERSIONis untouched. No CLI, config or plugin API surface changes.shouldGenerateThreadTitleis the only implementation of this rule in the repo, so no client-side duplicate needed updating.How you verified
Tests added (all fail on the parent commit, pass on this one — verified by reverting only the two source files and rerunning):
apps/server/test/threads/title-generation.test.ts— a bare skill invocation and a short one with arguments are both eligible; the raw command text is still the fallback; commands are collected once each in prompt order.apps/server/test/threads/generated-thread-titles.test.ts— the prompt sent to inference no longer contains the joined/sync-repo and droptext, does carry the invoked-commands sentence, and a plain prompt does not.Fixes #3886