- Restore Priority::Realtime handling in BackgroundExecutor::spawn_with_priority
- Spawns dedicated OS thread via dispatcher.spawn_realtime()
- Uses flume channel to send runnables to the dedicated thread
- Includes profiler timing integration for consistency with other dispatchers
- Delete orphaned crates/gpui/src/platform/platform_scheduler.rs (dead code)
- Fix test_parking_panics expected panic message
- All tests pass (GPUI, scheduler, editor)
- Clippy passes with no warnings
- Updated integration plan to mark all phases complete
Key outcomes:
- GPUI executors now use scheduler crate internally
- TestDispatcher simplified to ~70 lines (delegates to TestScheduler)
- PlatformScheduler implements Scheduler trait for production
- Blocking logic consolidated in Scheduler::block()
- Session IDs prevent foreground reentrancy when blocking
Design decisions documented:
- Foreground priority parameter kept for API compatibility but ignored
- Profiler integration unchanged (works through dispatcher layer)
- Runtime scheduler selection based on dispatcher type
Changes:
- Removed debug logging infrastructure from executor.rs
- Simplified block_internal to use waker_fn without Parker
- Removed unparkers mechanism from TestDispatcher
- TestDispatcher now just holds session_id and scheduler (~70 lines)
BROKEN: 3 editor tests fail:
- element::tests::test_soft_wrap_editor_width_auto_height_editor
- inlays::inlay_hints::tests::test_no_hint_updates_for_unrelated_language_files
- inlays::inlay_hints::tests::test_inside_char_boundary_range_hints
See crates/scheduler/full_integration_plan.md for investigation notes.
- Removed TaskLabel struct and its impl from gpui/src/executor.rs
- Removed spawn_labeled method from BackgroundExecutor
- Updated callers (buffer_diff, fs, language) to use regular spawn
- Removed label parameter from PlatformDispatcher::dispatch() trait
- Updated all dispatcher implementations (Mac, Linux, Windows, Test, PlatformScheduler)
- Fixed pre-existing dead code issues found during clippy
- TestDispatcher::simulate_random_delay() now delegates to TestScheduler::yield_random()
- Removed custom YieldNow future implementation (~20 lines)
- Cleaned up unused rand imports from gpui/src/executor.rs
- Fixed clippy warning about redundant async block in timer()
- Updated integration plan with next steps (Phase 4: Remove TaskLabel)
Attempted to delegate GPUI's block_internal to scheduler.block() but
encountered an issue with the blocked_sessions mechanism interfering
with user code calling tick() from within a blocked future.
Updated the plan to document this finding and possible solutions to
investigate. The current workaround (GPUI using tick() directly) works
but is not the final desired state.
- Create SharedRng type that wraps Arc<Mutex<StdRng>> and provides
convenient methods (random_range, random_bool, random, random_ratio)
that handle locking internally
- Update TestScheduler::rng() and BackgroundExecutor::rng() to return SharedRng
- SharedRng::lock() still available for cases needing &mut Rng
(e.g., slice::choose, Oid::random)
- Update call sites to use the cleaner API without explicit .lock() calls
- Fix collab tests to call .lock() on rng() before using Rng methods
- Update integration plan to add Phase 1: Create SharedRng wrapper type
that handles locking internally for better ergonomics
- BackgroundExecutor::timer() now uses Scheduler::timer() directly in tests
instead of dispatch_after with an empty task body
- Removed the 'delayed' queue from TestDispatcher entirely
- dispatch_after() now panics in tests (should never be called)
- is_main_thread() now delegated to TestScheduler
- advance_clock() and tick() are simple delegations to scheduler
- Removed start_waiting/finish_waiting methods (no longer needed)
- Added set_block_on_ticks() for test timeout control
- Made advance_clock_to_next_timer() public on TestScheduler
- Deleted situation.md (outdated investigation doc)
- Updated integration plan to reflect current state
TestDispatcher is now ~170 lines, down from 242, and mostly just
implements PlatformDispatcher by delegating to TestScheduler.
The plan now documents:
- All completed work (unified types, delegated queues, removed deprioritization, etc.)
- Current architecture with TestDispatcher as thin PlatformDispatcher wrapper
- Detailed strategy for eliminating PlatformDispatcher abstraction
- Phase-by-phase migration guide:
1. Add schedule_after to Scheduler trait
2. Move is_main_thread tracking into TestScheduler
3. Move unparker mechanism into TestScheduler
4. Create thin PlatformDispatcher impl for TestScheduler
5. Delete TestDispatcher
6-8. Longer term unification of Task/Executor types
The goal is to have GPUI use Scheduler trait directly and minimize
GPUI-specific scheduling code.
TestDispatcher no longer wraps scheduler methods like rng(), parking_allowed(),
allow_parking(), forbid_parking(). Callers now access these via scheduler() directly.
Removed methods:
- rng() -> use scheduler().rng()
- parking_allowed() -> use scheduler().parking_allowed()
- allow_parking() -> use scheduler().allow_parking()
- forbid_parking() -> use scheduler().forbid_parking()
TestDispatcher is now 242 lines (down from 263).
Further simplification of TestDispatcher:
- Remove waiting_hint and waiting_backtrace (scheduler has PENDING_TRACES)
- Remove start_waiting/finish_waiting/set_waiting_hint methods
- Remove block_on_ticks (use rng directly for timeout ticks)
- Remove all dispatcher_log! debug logging infrastructure
- Remove set_block_on_ticks from BackgroundExecutor
TestDispatcher is now 263 lines (down from 493).
TestDispatcherState now only contains:
- delayed: Vec<(Instant, RunnableVariant)> - for dispatch_after
- is_main_thread: bool - for PlatformDispatcher API
- unparkers: Vec<Unparker> - for block_on wakeup
This completes the major scheduler integration work:
**Task Queue Delegation**
- TestDispatcher now delegates foreground/background task scheduling to TestScheduler
- Each TestDispatcher instance gets a unique SessionId from TestScheduler
- dispatch() calls scheduler.schedule_background_with_priority()
- dispatch_on_main_thread() calls scheduler.schedule_foreground()
- Only the delayed queue remains local in TestDispatcher for dispatch_after()
**Unified Priority Types**
- Added RealtimePriority enum to scheduler crate
- Added Realtime(RealtimePriority) variant to scheduler's Priority enum
- GPUI now reexports Priority and RealtimePriority from scheduler
- Removed duplicate definitions from gpui/executor.rs
**Removed Deprioritization**
- Removed deprioritized_background queue from TestDispatcherState
- Removed deprioritize() from TestDispatcher and BackgroundExecutor
- Updated tests that relied on deprioritization
**New TestScheduler APIs**
- allocate_session_id(): Allocate session IDs for GPUI dispatcher instances
- tick(): Public interface to run one scheduler step
- tick_background_only(): Run only background tasks (no foreground)
- has_pending_tasks(): Check if work remains
- pending_task_counts(): Get (foreground, background) task counts
**Other Changes**
- executor.rng() now returns Arc<Mutex<StdRng>> instead of cloning
- Updated fake_git_repo.rs to use new rng() API
- Remove RunnableVariant::Compat variant entirely
- Update PlatformScheduler::timer() to use async_task::Builder with RunnableMeta
- Update REPL's ZedDispatcher to wrap external Runnable with metadata
- Simplify all platform dispatchers (Mac, Linux, Windows, Test):
- Remove Compat match arms
- Use let-binding pattern for single-variant enum
- Remove unused trampoline_compat function from Mac dispatcher
All tasks now carry source location information for better debugging
and profiling. The RunnableVariant enum is now single-variant and
could be simplified further in a future change.
Both GPUI and scheduler Task types now have identical APIs:
- ready(val) - create a task with an immediate value
- is_ready() - check if task has completed
- detach() - run task to completion in background
The only difference is GPUI's detach_and_log_err() which requires App context.
Phase 2a partial - Unified RunnableMeta:
- Re-export RunnableMeta from scheduler crate in gpui/src/platform.rs
- Remove GPUI's duplicate RunnableMeta struct definition
- Remove RunnableVariant::Scheduler variant (now uses Meta for both)
- Update all platform dispatchers to remove Scheduler variant handling
- Update PlatformScheduler to use RunnableVariant::Meta
Phase 3c - Execution tracking:
- Add execution_hash and execution_count to TestScheduler state
- Add execution_hash(), execution_count(), reset_execution_tracking() methods
- Update step() to track execution order via location hashing
- Enables determinism verification in tests
Note: Waiting hints (Phase 3b) skipped - TestScheduler already has
superior pending_traces system with TracingWaker that automatically
captures backtraces for all pending futures.
This commit integrates the scheduler crate's TestScheduler into GPUI's
TestDispatcher for deterministic testing. The TestDispatcher now uses
TestScheduler for:
- Clock/timing (via scheduler.clock())
- Random number generation (via scheduler.rng())
- Block-on tick configuration
GPUI's TestDispatcher maintains its own task queues (foreground, background,
delayed) because it needs to handle RunnableVariant with multiple variants
(Meta, Compat, Scheduler) that TestScheduler cannot process directly.
Key changes:
- TestDispatcher::new() now takes a seed (u64) instead of StdRng
- Clock and RNG are delegated to TestScheduler
- Added RunnableVariant::Scheduler for scheduler-based runnables
- Updated all platform dispatchers to handle the new variant
KNOWN ISSUE: Tests hang after completion. After running the collab
'workspace' tests, the test process hangs indefinitely after these pass:
- test_contact_requests
- test_server_restarts
- test_random_channel_buffers
- test_random_project_collaboration
The hang likely relates to teardown/cleanup when TestDispatcher shares
state with TestScheduler. Need to investigate:
1. Whether blocked_sessions in TestScheduler is properly cleaned up
2. Whether there are threads being parked that never get unparked
3. Whether the test macro teardown sequence interacts badly with scheduler
The test had a race condition where LSP request handlers were registered
AFTER typing the trigger character. Whether this worked depended on task
scheduling order, which varies by seed.
Changes:
- Move handler setup BEFORE typing the trigger character in the test
- Make TestDispatcher::spawn_realtime panic to prevent future non-determinism
from real OS threads escaping the deterministic test scheduler
- Add execution_hash() and execution_count() to TestDispatcher for debugging
- Add DEBUG_SCHEDULER=1 logging for task execution tracing
- Document the investigation in situation.md
Add the repository name when:
- there's more than one repository, and
- the name of the active repository doesn't match the name of the
project (to avoid stuttering with the adjacent project switcher button)
Release Notes:
- The branch name in the title bar now includes the name of the current
repository when needed to disambiguate.
- Edit prediction providers can now be configured through the settings
UI
- Cleaned up the status bar menu to only show _configured_ providers
- Added to the status bar icon button tooltip the name of the active
provider
- Only display the data collection functionality under "Privacy" for the
Zed models
- Moved the Codestral edit prediction provider out of the Mistral
section in the agent panel into the settings UI
- Refined and improved UI and states for configuring GitHub Copilot as
both an agent and edit prediction provider
#### Todos before merge:
- [x] UI: Unify with settings UI style and tidy it all up
- [x] Unify Copilot modal `impl`s to use separate window
- [x] Remove stop light icons from GitHub modal
- [x] Make dismiss events work on GitHub modal
- [ ] Investigate workarounds to tell if Copilot authenticated even when
LSP not running
Release Notes:
- settings_ui: Added a section for configuring edit prediction providers
under AI > Edit Predictions, including Codestral and GitHub Copilot.
Once you've updated you can use the following link to open it:
zed://settings/edit_predictions.providers
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
This fixes an issue where a user could get confused by the branch picker
because it would only show the 10 most recent branches, instead of all
branches.
Release Notes:
- git: Show all branches in branch picker when search field is empty
We were panicking whenever something went wrong with an example in the
CLI. This can be very disruptive when running many examples, and e.g a
single request fails. Instead, if running more than one example, errors
will now be logged alongside instructions to explore and re-run the
example by itself.
<img width="1454" height="744" alt="CleanShot 2025-12-12 at 13 32 04@2x"
src="https://github.com/user-attachments/assets/87c59e64-08b9-4461-af5b-03af5de94152"></img>
You can still opt in to stop as soon as en error occurs with the new
`--failfast` argument.
Release Notes:
- N/A
Improves the scheduler by allowing tasks to have a set priority which
will significantly improve responsiveness.
Release notes:
- N/A
---------
Co-authored-by: Yara <git@yara.blue>
Co-authored-by: dvdsk <noreply@davidsk.dev>
- Limit status lines to 10 in case `max_parallelism` is specified with a
grater value
- Handle logging gracefully rather than writing over it when clearing
status lines
Release Notes:
- N/A