Remove agent git worktree feature flag (#50778)

Remove the separate `AgentGitWorktreesFeatureFlag` and replace all its
checks with the existing `AgentV2FeatureFlag`. The git worktree
functionality is now gated behind the same flag as agent v2.

Changes:
- Removed `AgentGitWorktreesFeatureFlag` from `feature_flags`
- Replaced all `has_flag::<AgentGitWorktreesFeatureFlag>()` checks with
`has_flag::<AgentV2FeatureFlag>()`
- Simplified toolbar condition that was redundantly checking both flags
- Updated tests accordingly

Closes AI-73

Release Notes:

- N/A
This commit is contained in:
Richard Feldman authored and GitHub committed 2026-03-05 15:04:56 -05:00
1 parent fce1bde724
commit e3b299cce5
3 files changed
+6 -120

No files matched your search

+5 -106
View File
@@ -22,7 +22,7 @@ use project::{
use serde::{Deserialize, Serialize};
use settings::{LanguageModelProviderSetting, LanguageModelSelection};
use feature_flags::{AgentGitWorktreesFeatureFlag, AgentV2FeatureFlag, FeatureFlagAppExt as _};
use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt as _};
use zed_actions::agent::{OpenClaudeAgentOnboardingModal, ReauthenticateAgent, ReviewBranchDiff};
use crate::ManageProfiles;
@@ -695,7 +695,7 @@ impl AgentPanel {
}
if let Some(start_thread_in) = serialized_panel.start_thread_in {
let is_worktree_flag_enabled =
cx.has_flag::<AgentGitWorktreesFeatureFlag>();
cx.has_flag::<AgentV2FeatureFlag>();
let is_valid = match &start_thread_in {
StartThreadIn::LocalProject => true,
StartThreadIn::NewWorktree => {
@@ -1860,9 +1860,7 @@ impl AgentPanel {
}
fn set_start_thread_in(&mut self, action: &StartThreadIn, cx: &mut Context<Self>) {
if matches!(action, StartThreadIn::NewWorktree)
&& !cx.has_flag::<AgentGitWorktreesFeatureFlag>()
{
if matches!(action, StartThreadIn::NewWorktree) && !cx.has_flag::<AgentV2FeatureFlag>() {
return;
}
@@ -3496,9 +3494,7 @@ impl AgentPanel {
.pl(DynamicSpacing::Base04.rems(cx))
.pr(DynamicSpacing::Base06.rems(cx))
.when(
has_v2_flag
&& cx.has_flag::<AgentGitWorktreesFeatureFlag>()
&& !self.active_thread_has_messages(cx),
has_v2_flag && !self.active_thread_has_messages(cx),
|this| this.child(self.render_start_thread_in_selector(cx)),
)
.child(new_thread_menu)
@@ -4635,10 +4631,7 @@ mod tests {
async fn test_thread_target_serialization_round_trip(cx: &mut TestAppContext) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(
true,
vec!["agent-v2".to_string(), "agent-git-worktrees".to_string()],
);
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});
@@ -4725,100 +4718,6 @@ mod tests {
});
}
#[gpui::test]
async fn test_thread_target_deserialization_falls_back_when_worktree_flag_disabled(
cx: &mut TestAppContext,
) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(
true,
vec!["agent-v2".to_string(), "agent-git-worktrees".to_string()],
);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/project",
json!({
".git": {},
"src": {
"main.rs": "fn main() {}"
}
}),
)
.await;
fs.set_branch_name(Path::new("/project/.git"), Some("main"));
let project = Project::test(fs.clone(), [Path::new("/project")], cx).await;
let multi_workspace =
cx.add_window(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
let workspace = multi_workspace
.read_with(cx, |multi_workspace, _cx| {
multi_workspace.workspace().clone()
})
.unwrap();
workspace.update(cx, |workspace, _cx| {
workspace.set_random_database_id();
});
let cx = &mut VisualTestContext::from_window(multi_workspace.into(), cx);
// Wait for the project to discover the git repository.
cx.run_until_parked();
let panel = workspace.update_in(cx, |workspace, window, cx| {
let text_thread_store = cx.new(|cx| TextThreadStore::fake(project.clone(), cx));
let panel =
cx.new(|cx| AgentPanel::new(workspace, text_thread_store, None, window, cx));
workspace.add_panel(panel.clone(), window, cx);
panel
});
cx.run_until_parked();
panel.update(cx, |panel, cx| {
panel.set_start_thread_in(&StartThreadIn::NewWorktree, cx);
});
panel.read_with(cx, |panel, _cx| {
assert_eq!(
*panel.start_thread_in(),
StartThreadIn::NewWorktree,
"thread target should be NewWorktree before reload"
);
});
// Let serialization complete.
cx.run_until_parked();
// Disable worktree flag and reload panel from serialized data.
cx.update(|_, cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let prompt_builder = Arc::new(prompt_store::PromptBuilder::new(None).unwrap());
let async_cx = cx.update(|window, cx| window.to_async(cx));
let loaded_panel =
AgentPanel::load(workspace.downgrade(), prompt_builder.clone(), async_cx)
.await
.expect("panel load should succeed");
cx.run_until_parked();
loaded_panel.read_with(cx, |panel, _cx| {
assert_eq!(
*panel.start_thread_in(),
StartThreadIn::LocalProject,
"thread target should fall back to LocalProject when worktree flag is disabled"
);
});
}
#[gpui::test]
async fn test_set_active_blocked_during_worktree_creation(cx: &mut TestAppContext) {
init_test(cx);
-10
View File
@@ -37,16 +37,6 @@ impl FeatureFlag for AgentSharingFeatureFlag {
const NAME: &'static str = "agent-sharing";
}
pub struct AgentGitWorktreesFeatureFlag;
impl FeatureFlag for AgentGitWorktreesFeatureFlag {
const NAME: &'static str = "agent-git-worktrees";
fn enabled_for_staff() -> bool {
false
}
}
pub struct DiffReviewFeatureFlag;
impl FeatureFlag for DiffReviewFeatureFlag {
+1 -4
View File
@@ -3099,10 +3099,7 @@ fn run_start_thread_in_selector_visual_tests(
// Enable feature flags so the thread target selector renders
cx.update(|cx| {
cx.update_flags(
true,
vec!["agent-v2".to_string(), "agent-git-worktrees".to_string()],
);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
// Create a temp directory with a real git repo so "New Worktree" is enabled