Skip to content

Conversation

@ammar-agent
Copy link
Collaborator

@ammar-agent ammar-agent commented Feb 9, 2026

Summary

Seamless forking with workspace title management and centralized gateway routing. Forking now auto-generates deterministic numbered titles (Fix Bug (1)), with F2/Shift+F2 keybinds for manual rename and AI title regeneration. Gateway model routing is centralized in createModel so all callers get correct behavior automatically.

Background

Previously /fork <name> required a user-supplied branch name, adding friction. Additionally, gateway model routing was scattered across multiple call sites — the frontend had to pre-transform model IDs with formatAsGatewayModel to compensate for the backend's createModel not handling it, and the backend's regenerateTitle path was broken for gateway users entirely.

Implementation

Fork semantics

  • Fork titles use deterministic (N) suffix pattern: fork of "Fix Bug" → "Fix Bug (1)"
  • generateForkTitle(parent, existing) handles deduplication and suffix stripping

Workspace title management

  • F2: inline title editing, Shift+F2: AI-based title regeneration
  • workspace.regenerateTitle IPC reads history and calls generateWorkspaceIdentity
  • Shimmer loading state during generation
  • Full nomenclature audit: renametitle across UI and backend

Centralized gateway routing (addresses Codex review comment)

  • ProviderModelFactory.createModel() now calls resolveGatewayModelString internally (idempotent — already-resolved strings pass through unchanged)
  • Removed manual gateway resolution from system1ToolWrapper and AIService public API
  • Simplified frontend buildNameGenCandidates — no longer needs gateway transformation
  • Extracted NAME_GEN_PREFERRED_MODELS to shared constant at src/common/constants/nameGeneration.ts
  • Updated schema/router comments to reflect backend-authoritative routing

Validation

  • make typecheck — passes
  • make static-check — passes
  • make test — 3790 pass, 16 skip (1 pre-existing flaky failure unrelated to changes)
  • Targeted test suites: workspaceService, providerModelFactory, aiService, system1 — all pass

Generated with mux • Model: anthropic:claude-opus-4-6 • Thinking: xhigh • Cost: $51.40

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6b5afd6282

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ammar-agent ammar-agent force-pushed the fork-1z8m branch 2 times, most recently from d41c35d to 219caa0 Compare February 11, 2026 23:40
…ation

- Schema: add autoName flag to WorkspaceMetadata and WorkspaceConfig
- Backend: auto-generate fork branch names ({parent}-fork-N pattern)
  when /fork is used without an explicit name
- Backend: clear autoName flag on any title update (manual rename or
  auto-generated) to exit the provisional naming state
- Frontend: simplify /fork command - bare /fork works, everything after
  is treated as a start message
- Frontend: auto-name on first message via nameGeneration IPC
  (fire-and-forget, reuses existing LLM title generation pipeline)
- Frontend: italic styling in sidebar for auto-name workspaces
- Remove fork-help toast (no longer needed since bare /fork works)
- Tests: update fork command tests, add generateForkBranchName unit tests
Move the auto-naming trigger from ChatInput (frontend) to
WorkspaceService.sendMessage (backend), fixing three issues:

1. Eliminates duplicate candidate-building logic that was missing
   gateway model transforms (bug)
2. Includes prior assistant message from forked history for richer
   title generation context
3. Colocates the trigger with existing fire-and-forget side effects
   (updateRecencyTimestamp pattern)

Changes:
- Add autoGenerateTitle() private method to WorkspaceService
- Trigger from sendMessage after recency timestamp update
- Add assistantContext param to generateWorkspaceIdentity prompt
- Remove auto-naming block, refs, and imports from ChatInput
- Un-export NAME_GEN_PREFERRED_MODELS (now module-private)
- Add RENAME_WORKSPACE and REGENERATE_WORKSPACE_NAME to keybinds registry
- Add workspace.regenerateTitle backend endpoint (reads first user message +
  assistant reply from history, calls generateWorkspaceIdentity, persists via
  updateTitle)
- Add SidebarRenameKeybinds component inside RenameProvider for F2/Shift+F2
  (F2 enters inline edit mode, Shift+F2 calls regenerateTitle API)
- Update WorkspaceListItem context menu: F2 hint on 'Edit chat title',
  new 'Generate new title' item with Shift+F2 hint and Sparkles icon
- Add command palette entries with shortcut hints
- Add keybind labels + navigation group entries in KeybindsSection
All rename/name terminology updated to reflect that this feature is
about workspace *titles*, not workspace names/branches:

Keybinds:
- RENAME_WORKSPACE → EDIT_WORKSPACE_TITLE
- REGENERATE_WORKSPACE_NAME → GENERATE_WORKSPACE_TITLE

Commands:
- ws:rename → ws:edit-title (+ ws:rename-any → ws:edit-title-any)
- ws:regenerate-name → ws:generate-title

Context:
- WorkspaceRenameContext.tsx → WorkspaceTitleEditContext.tsx (git mv)
- RenameProvider → TitleEditProvider, useRename → useTitleEdit
- requestRename/confirmRename/cancelRename → requestEdit/confirmEdit/cancelEdit

WorkspaceContext:
- renameWorkspace → updateWorkspaceTitle
- onRenameWorkspace → onUpdateTitle (command palette sources + App.tsx)

Schema:
- autoName → autoTitle (project + workspace schemas, workspaceService)

UI strings updated: 'Rename Workspace' → 'Edit Workspace Title',
field labels from 'name' to 'title', initial values from .name to .title
When Shift+F2 or 'Generate new title' triggers regenerateTitle, the
sidebar title now shimmers (using the existing Shimmer component) and
renders in italic — matching the autoTitle placeholder style.

TitleEditContext gains generatingTitleWorkspaceId state and a
wrapGenerateTitle(workspaceId, asyncFn) helper that manages the
loading lifecycle. Both call sites (keybind handler in ProjectSidebar,
context menu in WorkspaceListItem) use the wrapper so the loading
state is consistent regardless of entry point.
Replace the lazy AI title generation on fork with a simple numbered
suffix: forking "Fix sidebar" produces "Fix sidebar (1)", then
"Fix sidebar (2)", etc. The suffix logic strips any existing "(N)"
from the parent title before incrementing, so forking "Fix sidebar (2)"
yields "Fix sidebar (3)" — not "Fix sidebar (2) (1)".

Removed:
- autoTitle field from project + workspace schemas
- autoGenerateTitle() method in WorkspaceService
- sendMessage trigger that called autoGenerateTitle on first message
- autoTitle clearing in updateTitle
- Italic styling for autoTitle in WorkspaceListItem

Users can still manually generate a new AI title any time via Shift+F2
or the context menu "Generate new title" action.

Added:
- generateForkTitle() helper (+ 5 unit tests)
Move gateway resolution from scattered call sites into
ProviderModelFactory.createModel(), so every model instantiation
automatically routes through the gateway when configured.

Changes:
- createModel now calls resolveGatewayModelString (idempotent)
- Remove manual gateway resolution from system1ToolWrapper
- Remove resolveGatewayModelString from AIService public API
- Simplify frontend buildNameGenCandidates (no gateway transform needed)
- Extract NAME_GEN_PREFERRED_MODELS to shared constant
- Update schema/router comments to reflect new behavior
@ammar-agent
Copy link
Collaborator Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c8e91ffbe

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

.get(props.selectedWorkspace.projectPath)
?.find((m) => m.id === wsId);
const displayTitle = meta?.title ?? meta?.name ?? "";
requestEdit(wsId, displayTitle);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prefill title when entering edit mode from keyboard shortcut

The F2 handler only calls requestEdit, but the inline input value is initialized in WorkspaceListItem.startEditing() and that path is bypassed here. As a result, pressing F2 opens edit mode with an empty input instead of the current title, and the subsequent blur/Enter path immediately trips the "Title cannot be empty" validation unless the user retypes the whole title manually. This breaks the advertised keyboard edit flow for selected workspaces.

Useful? React with 👍 / 👎.

Comment on lines +2077 to +2078
await this.updateTitle(workspaceId, result.data.title);
return Ok({ title: result.data.title });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Check updateTitle result before reporting regeneration success

regenerateTitle awaits updateTitle but ignores its Result, then always returns Ok with the generated title. If persistence fails (for example workspace lookup/config write failure), callers still get a success response even though no title was saved, which can leave UI and stored metadata out of sync and hide real errors.

Useful? React with 👍 / 👎.

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.

1 participant