ep: Follow-ups for binding changes (#52258) (cherry-pick to preview) (#52367)

zed-zippy[bot] , Ben Kunkle , and Max created

Cherry-pick of #52258 to preview

----
## Context

- Updates docs for how to update edit prediction bindings
- Walks back how often we use tab to accept prediction where we
previously didn't; now just when in leading whitespace, tab does not
accept completion when completions menu is open
- migration for keymaps using the old `edit_prediction_conflict` key
context

## How to Review

The only code worth reviewing is the migration
<!-- Help reviewers focus their attention:
- For small PRs: note what to focus on (e.g., "error handling in
foo.rs")
- For large PRs (>400 LOC): provide a guided tour — numbered list of
files/commits to read in order. (The `large-pr` label is applied
automatically.)
     - See the review process guidelines for comment conventions -->

## Self-Review Checklist

<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX

checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- N/A or Added/Fixed/Improved ...

---------

Co-authored-by: Max <max@zed.dev>

Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Max <max@zed.dev>

Change summary

assets/keymaps/default-linux.json                     |   2 
assets/keymaps/default-macos.json                     |   2 
assets/keymaps/default-windows.json                   |   2 
assets/keymaps/vim.json                               |   2 
crates/migrator/src/migrations.rs                     |   6 
crates/migrator/src/migrations/m_2026_03_23/keymap.rs |  47 +
crates/migrator/src/migrator.rs                       | 340 +++++++++---
7 files changed, 304 insertions(+), 97 deletions(-)

Detailed changes

assets/keymaps/default-linux.json 🔗

@@ -775,7 +775,7 @@
     },
   },
   {
-    "context": "Editor && edit_prediction && edit_prediction_mode == eager",
+    "context": "Editor && edit_prediction && edit_prediction_mode == eager && !showing_completions",
     "bindings": {
       "tab": "editor::AcceptEditPrediction",
     },

assets/keymaps/default-macos.json 🔗

@@ -839,7 +839,7 @@
     },
   },
   {
-    "context": "Editor && edit_prediction && edit_prediction_mode == eager",
+    "context": "Editor && edit_prediction && edit_prediction_mode == eager && !showing_completions",
     "bindings": {
       "tab": "editor::AcceptEditPrediction",
     },

assets/keymaps/default-windows.json 🔗

@@ -771,7 +771,7 @@
     },
   },
   {
-    "context": "Editor && edit_prediction && edit_prediction_mode == eager",
+    "context": "Editor && edit_prediction && edit_prediction_mode == eager && !showing_completions",
     "use_key_equivalents": true,
     "bindings": {
       "tab": "editor::AcceptEditPrediction",

assets/keymaps/vim.json 🔗

@@ -1060,7 +1060,7 @@
     },
   },
   {
-    "context": "Editor && edit_prediction && edit_prediction_mode == eager",
+    "context": "Editor && edit_prediction && edit_prediction_mode == eager && !showing_completions",
     "bindings": {
       // This is identical to the binding in the base keymap, but the vim bindings above to
       // "vim::Tab" shadow it, so it needs to be bound again.

crates/migrator/src/migrations.rs 🔗

@@ -310,3 +310,9 @@ pub(crate) mod m_2026_03_16 {
 
     pub(crate) use settings::SETTINGS_PATTERNS;
 }
+
+pub(crate) mod m_2026_03_23 {
+    mod keymap;
+
+    pub(crate) use keymap::KEYMAP_PATTERNS;
+}

crates/migrator/src/migrations/m_2026_03_23/keymap.rs 🔗

@@ -0,0 +1,47 @@
+use std::ops::Range;
+
+use tree_sitter::{Query, QueryMatch};
+
+use crate::MigrationPatterns;
+
+pub const KEYMAP_PATTERNS: MigrationPatterns =
+    &[(crate::patterns::KEYMAP_CONTEXT_PATTERN, rename_context_key)];
+
+fn rename_context_key(
+    contents: &str,
+    mat: &QueryMatch,
+    query: &Query,
+) -> Option<(Range<usize>, String)> {
+    let context_predicate_ix = query.capture_index_for_name("context_predicate")?;
+    let context_predicate_range = mat
+        .nodes_for_capture_index(context_predicate_ix)
+        .next()?
+        .byte_range();
+    let old_predicate = contents.get(context_predicate_range.clone())?.to_string();
+    let mut new_predicate = old_predicate.clone();
+
+    const REPLACEMENTS: &[(&str, &str)] = &[
+        (
+            "edit_prediction_conflict && !showing_completions",
+            "(edit_prediction && in_leading_whitespace)",
+        ),
+        (
+            "edit_prediction_conflict && showing_completions",
+            "(edit_prediction && showing_completions)",
+        ),
+        (
+            "edit_prediction_conflict",
+            "(edit_prediction && (showing_completions || in_leading_whitespace))",
+        ),
+    ];
+
+    for (old, new) in REPLACEMENTS {
+        new_predicate = new_predicate.replace(old, new);
+    }
+
+    if new_predicate != old_predicate {
+        Some((context_predicate_range, new_predicate))
+    } else {
+        None
+    }
+}

crates/migrator/src/migrator.rs 🔗

@@ -143,6 +143,10 @@ pub fn migrate_keymap(text: &str) -> Result<Option<String>> {
             migrations::m_2025_12_08::KEYMAP_PATTERNS,
             &KEYMAP_QUERY_2025_12_08,
         ),
+        MigrationType::TreeSitter(
+            migrations::m_2026_03_23::KEYMAP_PATTERNS,
+            &KEYMAP_QUERY_2026_03_23,
+        ),
     ];
     run_migrations(text, migrations)
 }
@@ -381,6 +385,10 @@ define_query!(
     SETTINGS_QUERY_2026_03_16,
     migrations::m_2026_03_16::SETTINGS_PATTERNS
 );
+define_query!(
+    KEYMAP_QUERY_2026_03_23,
+    migrations::m_2026_03_23::KEYMAP_PATTERNS
+);
 
 // custom query
 static EDIT_PREDICTION_SETTINGS_MIGRATION_QUERY: LazyLock<Query> = LazyLock::new(|| {
@@ -408,6 +416,7 @@ mod tests {
         }
     }
 
+    #[track_caller]
     fn assert_migrate_keymap(input: &str, output: Option<&str>) {
         let migrated = migrate_keymap(input).unwrap();
         pretty_assertions::assert_eq!(migrated.as_deref(), output);
@@ -426,7 +435,7 @@ mod tests {
     }
 
     #[track_caller]
-    fn assert_migrate_settings_with_migrations(
+    fn assert_migrate_with_migrations(
         migrations: &[MigrationType],
         input: &str,
         output: Option<&str>,
@@ -974,7 +983,7 @@ mod tests {
 
     #[test]
     fn test_mcp_settings_migration() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::TreeSitter(
                 migrations::m_2025_06_16::SETTINGS_PATTERNS,
                 &SETTINGS_QUERY_2025_06_16,
@@ -1163,7 +1172,7 @@ mod tests {
         }
     }
 }"#;
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::TreeSitter(
                 migrations::m_2025_06_16::SETTINGS_PATTERNS,
                 &SETTINGS_QUERY_2025_06_16,
@@ -1175,7 +1184,7 @@ mod tests {
 
     #[test]
     fn test_custom_agent_server_settings_migration() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::TreeSitter(
                 migrations::m_2025_11_20::SETTINGS_PATTERNS,
                 &SETTINGS_QUERY_2025_11_20,
@@ -1391,7 +1400,7 @@ mod tests {
 
     #[test]
     fn test_flatten_code_action_formatters_basic_array() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_01::flatten_code_actions_formatters,
             )],
@@ -1425,7 +1434,7 @@ mod tests {
 
     #[test]
     fn test_flatten_code_action_formatters_basic_object() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_01::flatten_code_actions_formatters,
             )],
@@ -1582,7 +1591,7 @@ mod tests {
     #[test]
     fn test_flatten_code_action_formatters_array_with_multiple_action_blocks_in_defaults_and_multiple_languages()
      {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_01::flatten_code_actions_formatters,
             )],
@@ -1708,7 +1717,7 @@ mod tests {
 
     #[test]
     fn test_flatten_code_action_formatters_array_with_format_on_save_and_multiple_languages() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_01::flatten_code_actions_formatters,
             )],
@@ -1895,7 +1904,7 @@ mod tests {
 
     #[test]
     fn test_format_on_save_formatter_migration_basic() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_02::remove_formatters_on_save,
             )],
@@ -1915,7 +1924,7 @@ mod tests {
 
     #[test]
     fn test_format_on_save_formatter_migration_array() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_02::remove_formatters_on_save,
             )],
@@ -1940,7 +1949,7 @@ mod tests {
 
     #[test]
     fn test_format_on_save_on_off_unchanged() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_02::remove_formatters_on_save,
             )],
@@ -1951,7 +1960,7 @@ mod tests {
             None,
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_02::remove_formatters_on_save,
             )],
@@ -1965,7 +1974,7 @@ mod tests {
 
     #[test]
     fn test_format_on_save_formatter_migration_in_languages() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_02::remove_formatters_on_save,
             )],
@@ -2003,7 +2012,7 @@ mod tests {
 
     #[test]
     fn test_format_on_save_formatter_migration_mixed_global_and_languages() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_02::remove_formatters_on_save,
             )],
@@ -2040,7 +2049,7 @@ mod tests {
 
     #[test]
     fn test_format_on_save_no_migration_when_no_format_on_save() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_02::remove_formatters_on_save,
             )],
@@ -2054,7 +2063,7 @@ mod tests {
 
     #[test]
     fn test_restore_code_actions_on_format() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_16::restore_code_actions_on_format,
             )],
@@ -2075,7 +2084,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_16::restore_code_actions_on_format,
             )],
@@ -2089,7 +2098,7 @@ mod tests {
             None,
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_16::restore_code_actions_on_format,
             )],
@@ -2116,7 +2125,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_16::restore_code_actions_on_format,
             )],
@@ -2145,7 +2154,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_16::restore_code_actions_on_format,
             )],
@@ -2163,7 +2172,7 @@ mod tests {
 
     #[test]
     fn test_make_file_finder_include_ignored_an_enum() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum,
             )],
@@ -2171,7 +2180,7 @@ mod tests {
             None,
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum,
             )],
@@ -2191,7 +2200,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum,
             )],
@@ -2211,7 +2220,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum,
             )],
@@ -2232,7 +2241,7 @@ mod tests {
         );
 
         // Platform key: settings nested inside "linux" should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum,
             )],
@@ -2261,7 +2270,7 @@ mod tests {
         );
 
         // Profile: settings nested inside profiles should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum,
             )],
@@ -2296,7 +2305,7 @@ mod tests {
 
     #[test]
     fn test_make_relative_line_numbers_an_enum() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_21::make_relative_line_numbers_an_enum,
             )],
@@ -2304,7 +2313,7 @@ mod tests {
             None,
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_21::make_relative_line_numbers_an_enum,
             )],
@@ -2320,7 +2329,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_21::make_relative_line_numbers_an_enum,
             )],
@@ -2337,7 +2346,7 @@ mod tests {
         );
 
         // Platform key: settings nested inside "macos" should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_21::make_relative_line_numbers_an_enum,
             )],
@@ -2362,7 +2371,7 @@ mod tests {
         );
 
         // Profile: settings nested inside profiles should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_10_21::make_relative_line_numbers_an_enum,
             )],
@@ -2439,7 +2448,7 @@ mod tests {
         );
 
         // Platform key: settings nested inside "linux" should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_11_25::remove_context_server_source,
             )],
@@ -2477,7 +2486,7 @@ mod tests {
         );
 
         // Profile: settings nested inside profiles should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_11_25::remove_context_server_source,
             )],
@@ -2618,7 +2627,7 @@ mod tests {
     #[test]
     fn test_make_auto_indent_an_enum() {
         // Empty settings should not change
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_01_27::make_auto_indent_an_enum,
             )],
@@ -2627,7 +2636,7 @@ mod tests {
         );
 
         // true should become "syntax_aware"
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_01_27::make_auto_indent_an_enum,
             )],
@@ -2644,7 +2653,7 @@ mod tests {
         );
 
         // false should become "none"
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_01_27::make_auto_indent_an_enum,
             )],
@@ -2661,7 +2670,7 @@ mod tests {
         );
 
         // Already valid enum values should not change
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_01_27::make_auto_indent_an_enum,
             )],
@@ -2673,7 +2682,7 @@ mod tests {
         );
 
         // Should also work inside languages
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2025_01_27::make_auto_indent_an_enum,
             )],
@@ -2702,7 +2711,7 @@ mod tests {
 
     #[test]
     fn test_move_edit_prediction_provider_to_edit_predictions() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
             )],
@@ -2710,7 +2719,7 @@ mod tests {
             None,
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
             )],
@@ -2734,7 +2743,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
             )],
@@ -2762,7 +2771,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
             )],
@@ -2789,7 +2798,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
             )],
@@ -2806,7 +2815,7 @@ mod tests {
 
         // Non-object edit_predictions (e.g. true) should gracefully skip
         // instead of bail!-ing and aborting the entire migration chain.
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
             )],
@@ -2830,7 +2839,7 @@ mod tests {
         );
 
         // Platform key: settings nested inside "macos" should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
             )],
@@ -2859,7 +2868,7 @@ mod tests {
         );
 
         // Profile: settings nested inside profiles should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
             )],
@@ -2892,7 +2901,7 @@ mod tests {
         );
 
         // Combined: root + platform + profile should all be migrated simultaneously
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
             )],
@@ -2943,7 +2952,7 @@ mod tests {
 
     #[test]
     fn test_migrate_experimental_sweep_mercury() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
             )],
@@ -2951,7 +2960,7 @@ mod tests {
             None,
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
             )],
@@ -2977,7 +2986,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
             )],
@@ -3003,7 +3012,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
             )],
@@ -3029,7 +3038,7 @@ mod tests {
             ),
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
             )],
@@ -3044,7 +3053,7 @@ mod tests {
             None,
         );
 
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
             )],
@@ -3062,7 +3071,7 @@ mod tests {
         );
 
         // Platform key: settings nested inside "linux" should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
             )],
@@ -3093,7 +3102,7 @@ mod tests {
         );
 
         // Profile: settings nested inside profiles should be migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
             )],
@@ -3128,7 +3137,7 @@ mod tests {
         );
 
         // Combined: root + platform + profile should all be migrated simultaneously
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
             )],
@@ -3186,7 +3195,7 @@ mod tests {
     #[test]
     fn test_migrate_always_allow_tool_actions_to_default() {
         // No agent settings - no change
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3195,7 +3204,7 @@ mod tests {
         );
 
         // always_allow_tool_actions: true -> tool_permissions.default: "allow"
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3222,7 +3231,7 @@ mod tests {
         );
 
         // always_allow_tool_actions: false -> just remove it
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3241,7 +3250,7 @@ mod tests {
         );
 
         // Preserve existing tool_permissions.tools when migrating
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3280,7 +3289,7 @@ mod tests {
         );
 
         // Don't override existing default (and migrate default_mode to default)
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3310,7 +3319,7 @@ mod tests {
         );
 
         // Migrate existing default_mode to default (no always_allow_tool_actions)
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3339,7 +3348,7 @@ mod tests {
         );
 
         // No migration needed if already using new format with "default"
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3357,7 +3366,7 @@ mod tests {
         );
 
         // Migrate default_mode to default in tool-specific rules
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3396,7 +3405,7 @@ mod tests {
         );
 
         // When tool_permissions is null, replace it so always_allow is preserved
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3424,7 +3433,7 @@ mod tests {
         );
 
         // Platform-specific agent migration
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3455,7 +3464,7 @@ mod tests {
         );
 
         // Channel-specific agent migration
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3496,7 +3505,7 @@ mod tests {
         );
 
         // Profile-level migration
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3534,7 +3543,7 @@ mod tests {
         );
 
         // Platform-specific agent with profiles
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3579,7 +3588,7 @@ mod tests {
         );
 
         // Root-level profile with always_allow_tool_actions
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3614,7 +3623,7 @@ mod tests {
         );
 
         // Root-level profile with default_mode
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3651,7 +3660,7 @@ mod tests {
         );
 
         // Root-level profile + root-level agent both migrated
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3697,7 +3706,7 @@ mod tests {
 
         // Non-boolean always_allow_tool_actions (string "true") is left in place
         // so the schema validator can report it, rather than silently dropping user data.
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3713,7 +3722,7 @@ mod tests {
         );
 
         // null always_allow_tool_actions is removed (treated as false)
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3730,7 +3739,7 @@ mod tests {
 
         // Project-local settings (.zed/settings.json) with always_allow_tool_actions
         // These files have no platform/channel overrides or root-level profiles.
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3771,7 +3780,7 @@ mod tests {
         );
 
         // Project-local settings with only default_mode (no always_allow_tool_actions)
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3800,7 +3809,7 @@ mod tests {
         );
 
         // Project-local settings with no agent section at all - no change
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3815,7 +3824,7 @@ mod tests {
         );
 
         // Existing agent_servers are left untouched
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3858,7 +3867,7 @@ mod tests {
         );
 
         // Existing agent_servers are left untouched even with partial entries
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3895,7 +3904,7 @@ mod tests {
         );
 
         // always_allow_tool_actions: false leaves agent_servers untouched
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_04::migrate_tool_permission_defaults,
             )],
@@ -3918,7 +3927,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_to_registry_simple() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -3958,7 +3967,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_empty_entries() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -3989,7 +3998,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_with_command() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4027,7 +4036,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_gemini_with_command() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4055,7 +4064,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_gemini_ignore_system_version_false() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4083,7 +4092,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_gemini_ignore_system_version_true() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4110,7 +4119,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_already_typed_unchanged() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4132,7 +4141,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_preserves_custom_entries() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4166,7 +4175,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_target_already_exists() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4196,7 +4205,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_no_agent_servers_key() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4211,7 +4220,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_all_fields() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4259,7 +4268,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_codex_with_command() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4291,7 +4300,7 @@ mod tests {
 
     #[test]
     fn test_migrate_builtin_agent_servers_mixed_migrated_and_not() {
-        assert_migrate_settings_with_migrations(
+        assert_migrate_with_migrations(
             &[MigrationType::Json(
                 migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry,
             )],
@@ -4326,4 +4335,149 @@ mod tests {
             ),
         );
     }
+
+    #[test]
+    fn test_migrate_edit_prediction_conflict_context() {
+        assert_migrate_with_migrations(
+            &[MigrationType::TreeSitter(
+                migrations::m_2026_03_23::KEYMAP_PATTERNS,
+                &KEYMAP_QUERY_2026_03_23,
+            )],
+            &r#"
+            [
+                {
+                    "context": "Editor && edit_prediction_conflict",
+                    "bindings": {
+                        "ctrl-enter": "editor::AcceptEditPrediction" // Example of a modified keybinding
+                    }
+                }
+            ]
+            "#.unindent(),
+            Some(
+                &r#"
+                [
+                    {
+                        "context": "Editor && (edit_prediction && (showing_completions || in_leading_whitespace))",
+                        "bindings": {
+                            "ctrl-enter": "editor::AcceptEditPrediction" // Example of a modified keybinding
+                        }
+                    }
+                ]
+                "#.unindent(),
+            ),
+        );
+
+        assert_migrate_with_migrations(
+            &[MigrationType::TreeSitter(
+                migrations::m_2026_03_23::KEYMAP_PATTERNS,
+                &KEYMAP_QUERY_2026_03_23,
+            )],
+            &r#"
+            [
+                {
+                    "context": "Editor && edit_prediction_conflict && !showing_completions",
+                    "bindings": {
+                        // Here we don't require a modifier unless there's a language server completion
+                        "tab": "editor::AcceptEditPrediction"
+                    }
+                }
+            ]
+            "#.unindent(),
+            Some(
+                &r#"
+                [
+                    {
+                        "context": "Editor && (edit_prediction && in_leading_whitespace)",
+                        "bindings": {
+                            // Here we don't require a modifier unless there's a language server completion
+                            "tab": "editor::AcceptEditPrediction"
+                        }
+                    }
+                ]
+                "#.unindent(),
+            ),
+        );
+
+        assert_migrate_with_migrations(
+            &[MigrationType::TreeSitter(
+                migrations::m_2026_03_23::KEYMAP_PATTERNS,
+                &KEYMAP_QUERY_2026_03_23,
+            )],
+            &r#"
+            [
+                {
+                    "context": "Editor && edit_prediction_conflict && showing_completions",
+                    "bindings": {
+                        "tab": "editor::AcceptEditPrediction"
+                    }
+                }
+            ]
+            "#
+            .unindent(),
+            Some(
+                &r#"
+                [
+                    {
+                        "context": "Editor && (edit_prediction && showing_completions)",
+                        "bindings": {
+                            "tab": "editor::AcceptEditPrediction"
+                        }
+                    }
+                ]
+                "#
+                .unindent(),
+            ),
+        );
+
+        assert_migrate_with_migrations(
+            &[MigrationType::TreeSitter(
+                migrations::m_2026_03_23::KEYMAP_PATTERNS,
+                &KEYMAP_QUERY_2026_03_23,
+            )],
+            &r#"
+            [
+                {
+                    "context": "Editor && edit_prediction",
+                    "bindings": {
+                        "tab": "editor::AcceptEditPrediction",
+                        // Optional: This makes the default `alt-l` binding do nothing.
+                        "alt-l": null
+                    }
+                },
+                {
+                    "context": "Editor && edit_prediction_conflict",
+                    "bindings": {
+                        "alt-tab": "editor::AcceptEditPrediction",
+                        // Optional: This makes the default `alt-l` binding do nothing.
+                        "alt-l": null
+                    }
+                },
+            ]
+            "#
+            .unindent(),
+            Some(
+                &r#"
+                    [
+                        {
+                            "context": "Editor && edit_prediction",
+                            "bindings": {
+                                "tab": "editor::AcceptEditPrediction",
+                                // Optional: This makes the default `alt-l` binding do nothing.
+                                "alt-l": null
+                            }
+                        },
+                        {
+                            "context": "Editor && (edit_prediction && (showing_completions || in_leading_whitespace))",
+                            "bindings": {
+                                "alt-tab": "editor::AcceptEditPrediction",
+                                // Optional: This makes the default `alt-l` binding do nothing.
+                                "alt-l": null
+                            }
+                        },
+                    ]
+                "#
+                .unindent(),
+            ),
+        );
+    }
 }