e2e: project discovery, worktree spawn on new and existing branches, guarded cleanup #66

Closed
opened 2026-08-23 19:29:23 +01:00 by naps62-yolo · 1 comment
Collaborator

Cover the new spawn path end to end in crates/maestro-e2e, against real git and tmux with a temp $HOME and TMUX_TMPDIR, as the existing tests there do.

  • A temp root holding two git repositories, configured as [spawn].project_roots, is discovered by GET /api/projects, with last_activity reflecting HEAD mtime and spawn history.
  • GET /api/branches lists the repository's branches and flags one already held by a worktree.
  • Spawning with a new branch creates the worktree at <repo>/worktrees/<branch> and the session runs in it.
  • Spawning with an existing branch checks that branch out rather than creating one.
  • A second spawn onto the same branch is rejected rather than producing a broken worktree.
  • Killing the session removes a clean worktree.
  • Killing a session whose worktree has uncommitted changes leaves it on disk and reports it, rather than force-removing.

That last case is the guard the whole "cleanup is unconditional" decision rests on, so it is the one that must not be skipped.

Depends on: #56, #61

Cover the new spawn path end to end in `crates/maestro-e2e`, against real `git` and `tmux` with a temp `$HOME` and `TMUX_TMPDIR`, as the existing tests there do. - A temp root holding two git repositories, configured as `[spawn].project_roots`, is discovered by `GET /api/projects`, with `last_activity` reflecting HEAD mtime and spawn history. - `GET /api/branches` lists the repository's branches and flags one already held by a worktree. - Spawning with a **new** branch creates the worktree at `<repo>/worktrees/<branch>` and the session runs in it. - Spawning with an **existing** branch checks that branch out rather than creating one. - A second spawn onto the same branch is rejected rather than producing a broken worktree. - Killing the session removes a clean worktree. - Killing a session whose worktree has uncommitted changes leaves it on disk and reports it, rather than force-removing. That last case is the guard the whole "cleanup is unconditional" decision rests on, so it is the one that must not be skipped. Depends on: #56, #61
naps62-yolo added this to the Spawn v2 milestone 2026-08-23 19:29:23 +01:00
naps62-yolo added the area/daemondifficulty/mediumtype/test labels 2026-08-23 19:29:23 +01:00
Author
Collaborator

Integrated into blitz/spawn-v2. All seven cases landed, plus spawn_from_linked_worktree_places_in_main_checkout, which covers the nested-worktree data loss a review caught.

The e2e binary runs 17 tests in 46s, all passing against real tmux and git. The guarded-cleanup case logs what it refused, which is the behaviour the unconditional-cleanup decision rests on:

WARN left worktree on disk path=/tmp/.tmpHOKG2s/worktrees/feature-unsaved
     error=has uncommitted changes
Integrated into `blitz/spawn-v2`. All seven cases landed, plus `spawn_from_linked_worktree_places_in_main_checkout`, which covers the nested-worktree data loss a review caught. The e2e binary runs 17 tests in 46s, all passing against real tmux and git. The guarded-cleanup case logs what it refused, which is the behaviour the unconditional-cleanup decision rests on: ``` WARN left worktree on disk path=/tmp/.tmpHOKG2s/worktrees/feature-unsaved error=has uncommitted changes ```
This repo is archived. You cannot comment on issues.
1 Participants
Due Date
No due date set.
Reference: naps62/maestro#66