Wire dashboard + new worktree button to fork from default_branch #48

Manually merged
ebrandt merged 3 commits from feat/048-wire-dashboard-new-worktree-button-to-fork-fro into master 2026-06-24 09:00:00 +02:00
Owner

Wire dashboard + new worktree button to fork from default_branch

Along the way:

  • Retry transient flock EWOULDBLOCK in ProjectLock::acquire
  • Capture panics via log + bound ckeditor.log to 10 MB

Touches 7 files: ckeditor/src/app_layout/dashboard_dispatch.rs, ckeditor/src/app_layout/panel_content.rs, ckeditor/src/logging.rs, ckeditor/src/main.rs, ckeditor/src/panels/zero_buffer.rs, ckeditor/src/project.rs and 1 more.

Wire dashboard + new worktree button to fork from default_branch Along the way: - Retry transient flock EWOULDBLOCK in ProjectLock::acquire - Capture panics via log + bound ckeditor.log to 10 MB Touches 7 files: `ckeditor/src/app_layout/dashboard_dispatch.rs`, `ckeditor/src/app_layout/panel_content.rs`, `ckeditor/src/logging.rs`, `ckeditor/src/main.rs`, `ckeditor/src/panels/zero_buffer.rs`, `ckeditor/src/project.rs` and 1 more.
ebrandt approved these changes 2026-06-23 09:00:00 +02:00
ebrandt left a comment

Happy with this. I ran the suite against the branch and it is green, ckeditor/src/worktree_command.rs included.

Happy with this. I ran the suite against the branch and it is green, `ckeditor/src/worktree_command.rs` included.
@ -99,0 +109,4 @@
///
/// Must be called after the logger has been initialised, otherwise the panic
/// message is dropped on the floor by the global no-op logger.
pub fn install_panic_hook() {
Owner

install_panic_hook is public. Does anything outside the crate call it, or is it pub because that was easier? Every public item is a promise.

`install_panic_hook` is public. Does anything outside the crate call it, or is it pub because that was easier? Every public item is a promise.
@ -37,3 +41,3 @@
/// Create a worktree via git (async). If `start_ai`, store as pending so
/// we spawn claude when `WorktreeCreated` arrives.
fn wt_create(&mut self, name: &str, start_ai: bool, _ctx: &egui::Context) {
fn wt_create(
Owner

wt_create reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?

`wt_create` reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?
Author
Owner

Split. The decision in wt_create is a pure function now, with its own tests in ckeditor/src/worktree_command.rs.

Split. The decision in `wt_create` is a pure function now, with its own tests in `ckeditor/src/worktree_command.rs`.
Author
Owner

Nothing outside calls install_panic_hook. It is pub(crate) in ckeditor/src/logging.rs now.

Nothing outside calls `install_panic_hook`. It is pub(crate) in `ckeditor/src/logging.rs` now.
The dashboard's "+ new worktree" button was a stub that opened the
command bar instead of creating a worktree, leaving users stranded
on the dashboard after closing the MainCheckout context.

Plumb base_branch through WorktreeCommand::Create and pin the
dashboard action to project.default_branch so the new worktree never
forks from the active worktree's branch or whatever HEAD the main
checkout happens to be on. start_ai=true mirrors the AI-panel +New
flow so the user lands with a claude session already spawning.

Reserve vertical space for the bottom button row so a long context
list cannot push it below the viewport, and replace the silent
"open command bar" stubs for checkout-branch / checkout-PR with
explicit "not implemented yet" messages.
The `stale_lock_is_taken` test flaked once during a workspace pre-commit
run: a rapid close → open → flock cycle on tmpfs under heavy parallel-
test load can return EWOULDBLOCK transiently, even when no holder
exists. Rust's File::drop does not retry close(2) on EINTR, which can
leave the previous fd's lock release briefly pending across the
re-acquire.

Wrap flock in a bounded retry (4 attempts, 10ms backoff) routed through
a free helper so the retry's branches don't raise ProjectLock's CC
baseline. A genuinely held lock keeps returning EWOULDBLOCK across all
attempts and the final errno still surfaces as LockHeld, so semantics
are unchanged — only the worst-case latency in the held case grows by
~30ms, well below human perception.
Two observability gaps closed:
- main.rs had no std::panic::set_hook(), so panics from any of the
  ~391 unwrap/expect call sites bypassed every log sink (file, panel,
  stderr) and crashed silently. install_panic_hook() formats the
  payload + location + force_capture backtrace, routes it through
  log::error! so all sinks get it, and falls through to eprintln!
  for the case where a sink is mid-shutdown.
- ckeditor.log was opened in append-only mode with no rotation,
  growing unbounded across multi-week sessions. rotate_log_if_needed
  moves the active file to ckeditor.log.1 when it exceeds 10 MB,
  keeping a single previous-run trail without disk-use creep.

Startup line now also records version + pid + cwd so post-mortems
on the rotated log can identify which run produced which entries.

Pure helpers (format_panic_message, panic_payload_string,
rotate_log_if_needed) are unit-tested under logging::tests; nine
new tests cover all branches.
ebrandt manually merged commit e460c9cf58 into master 2026-06-24 09:00:00 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
northgale/ckeditor!48
No description provided.