Follow-up from the 2026-07-30 upstream sync stack (#190–#196). Surfaced by the Codex reviewer on #195 and confirmed by triage.
Problem
Upstream's thread title regeneration (pingdotgg#4810) assumes every selectable text-generation instance can produce a title. That holds for all five upstream drivers — Codex, Claude, Cursor, Grok and OpenCode all implement generateThreadTitle for real.
This fork ships four instances that structurally cannot:
apps/server/src/textGeneration/AmpTextGeneration.ts
apps/server/src/textGeneration/CopilotTextGeneration.ts
apps/server/src/textGeneration/GeminiCliTextGeneration.ts
apps/server/src/provider/Drivers/DroidDriver.ts (inline stub — no separate module)
They unconditionally Effect.fail(new TextGenerationError(...)).
regenerateThreadTitle resolves the generator from the global serverSettingsService.getSettings.textGenerationModelSelection, not the thread's provider. The Effect.catchCause in ProviderCommandReactor.ts then converts that failure into a successful completion with no title. Result: the user picks "Regenerate title", the spinner appears and clears, and the title is unchanged with no error.
Nothing gates the action — capabilities.threadTitleRegeneration is hardcoded true, the sidebar menu keys off that flag alone, and the settings UI offers every registered instance as the text-generation instance with no capability filter. There is no supportsTextGeneration concept in the repo.
Why it wasn't fixed in the sync stack
The obvious cheap fix — deriving capabilities.threadTitleRegeneration from whether the configured instance supports text generation — does not work. The descriptor is built once at startup in ServerEnvironment.ts (getDescriptor: Effect.succeed(descriptor)), while the text-generation instance is a runtime setting, so the flag would be stale as soon as the user changes it.
Suggested fix
Carry the failure through instead of swallowing it:
- Add an optional
error field to ThreadTitleRegenerationCompleteCommand in packages/contracts/src/orchestration.ts and its projected event.
- In
ProviderCommandReactor.ts, pass TextGenerationError.detail into dispatchThreadTitleRegenerationCompletion rather than dropping it.
- Project it onto
thread.titleRegeneration and surface it as a toast in SidebarV2.
This also fixes the general case: the same catchCause swallows transient CLI and network failures on upstream too. The fork's stub drivers merely make it fail 100% of the time, which is why it became visible here. Worth reporting upstream as well.
Compare GitManager.ts, where generateCommitMessage failures propagate as typed errors to the RPC caller and a stub driver produces a visible error — title regeneration is the only text-gen path that silently completes.
Follow-up from the 2026-07-30 upstream sync stack (#190–#196). Surfaced by the Codex reviewer on #195 and confirmed by triage.
Problem
Upstream's thread title regeneration (pingdotgg#4810) assumes every selectable text-generation instance can produce a title. That holds for all five upstream drivers — Codex, Claude, Cursor, Grok and OpenCode all implement
generateThreadTitlefor real.This fork ships four instances that structurally cannot:
apps/server/src/textGeneration/AmpTextGeneration.tsapps/server/src/textGeneration/CopilotTextGeneration.tsapps/server/src/textGeneration/GeminiCliTextGeneration.tsapps/server/src/provider/Drivers/DroidDriver.ts(inline stub — no separate module)They unconditionally
Effect.fail(new TextGenerationError(...)).regenerateThreadTitleresolves the generator from the globalserverSettingsService.getSettings.textGenerationModelSelection, not the thread's provider. TheEffect.catchCauseinProviderCommandReactor.tsthen converts that failure into a successful completion with no title. Result: the user picks "Regenerate title", the spinner appears and clears, and the title is unchanged with no error.Nothing gates the action —
capabilities.threadTitleRegenerationis hardcodedtrue, the sidebar menu keys off that flag alone, and the settings UI offers every registered instance as the text-generation instance with no capability filter. There is nosupportsTextGenerationconcept in the repo.Why it wasn't fixed in the sync stack
The obvious cheap fix — deriving
capabilities.threadTitleRegenerationfrom whether the configured instance supports text generation — does not work. The descriptor is built once at startup inServerEnvironment.ts(getDescriptor: Effect.succeed(descriptor)), while the text-generation instance is a runtime setting, so the flag would be stale as soon as the user changes it.Suggested fix
Carry the failure through instead of swallowing it:
errorfield toThreadTitleRegenerationCompleteCommandinpackages/contracts/src/orchestration.tsand its projected event.ProviderCommandReactor.ts, passTextGenerationError.detailintodispatchThreadTitleRegenerationCompletionrather than dropping it.thread.titleRegenerationand surface it as a toast inSidebarV2.This also fixes the general case: the same
catchCauseswallows transient CLI and network failures on upstream too. The fork's stub drivers merely make it fail 100% of the time, which is why it became visible here. Worth reporting upstream as well.Compare
GitManager.ts, wheregenerateCommitMessagefailures propagate as typed errors to the RPC caller and a stub driver produces a visible error — title regeneration is the only text-gen path that silently completes.