Skip to content

feat(app): stopping several agents can archive their worktrees too - #179

Merged
sean-brydon merged 2 commits into
cosscom:mainfrom
Stener1:bulk-stop-archive
Oct 22, 2026
Merged

sean-brydon merged 2 commits into
cosscom:mainfrom
Stener1:bulk-stop-archive

Conversation

@Stener1

@Stener1 Stener1 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

On the Agent Dashboard you pick several finished agents and Stop them, but their worktrees stay. To finish the work you then open each worktree and archive it, one at a time. The Stop and Clean up dialogs now have Archive their worktrees where it's safe.

run (ticked)
  stopAgents                      # as before, 3 at a time
  archiveStopped
    fresh session listing per box # a box that doesn't answer keeps its worktrees
    planArchive                   # lib/archive-after-stop.ts, pure, unit-tested
      each worktree once, never the main checkout
      keep: an agent there didn't stop
      keep: another agent live in it or a folder under it
    removeWorktreeOnBox(…, "archive")   # one at a time per box, boxes side by side
      git refuses dirty → "Kept: uncommitted changes"
  kept or failed → dialog stays open, each row says why
  else           → toast "Stopped 3 agents · archived 2 worktrees"
  • The box is off at first and remembered (berth.dashboard.stopArchives). It shows only when a picked agent works in a worktree that isn't the main checkout. Unticked, the dialog is as before.
  • Box fix: dropWorktree stopped services and ran the archive script before git refused a dirty worktree. The teardown ran on work that was then kept, and the box had already answered 202 "archiving". It now checks git status first and refuses in git's own words. This applies to every Archive and Remove path (sidebar, Worktrees table, this dialog); force still skips it.
  • The dialog keeps git's dirty-refusal check (keepsWork) and the archive wording local, matching the Worktrees table. It doesn't touch remove-worktree.ts, use-bulk.ts or the sidebar, so it merges cleanly beside other work on archiving there. Moving keepsWork to one shared place is a small follow-up.

Evidence

Driven with the verify skill's new dashboard-stop-archive scenario (production build, mock fixtures, Chromium, no console errors). Four agents are picked so that every outcome shows.

Before (main): only Stop After: the box, ticked
before ticked
Done: archiving, archived, kept ×2 Worktrees table after: search-perf and ci-flake gone Clean up remembers the choice
done after cleanup

On a real box (dev-box.sh up, then the new scripts/archive-dirty-live.sh, which goes through the laptop agent's API):

dirty: {"code":"git_failed","error":"git worktree remove: '…/acme-shop-verify-dirty' contains modified or untracked files, use --force to delete it"}  400
clean: {"archive":"echo \"ran in $PWD\" >> …/ran.log","removing":"verify-clean"}  202
OK: dirty refused before its script, clean archived

Before the fix the box took that request asynchronously (202) and ran the script first. The Go test below shows this, failing on the unfixed code; I didn't drive a box built from main.

Tests:

  • TestADirtyWorktreeIsRefusedBeforeItsArchiveScriptRuns failed before the fix (async=true err=<nil>) and passes after.
  • archive-after-stop.test.ts (5) covers: archived once per worktree; main checkout and loose agents are never candidates; another live agent (root or subfolder, not a sibling path) keeps it; partial or total stop failure; a box that didn't list keeps its worktrees.
  • e2e/dashboard-stop-archive.spec.ts (4) covers: ticked → clean archived and dirty kept, dialog open; another agent → kept; unticked → nothing archived; choice remembered, and no box for a main checkout alone. 20/20 with --repeat-each=5.
  • The checks from AGENTS.md (go vet, go test -race ./..., the app checks, pnpm test 577, build, tsc -p e2e, docs build) all pass.
    • internal/agent and leadline/api failed once under the full -race run and passed on rerun.
    • keyboard.spec.ts "⌘⇧E … Files panel" fails on main too.

Not shown here: the app driving a real box's agents through this dialog. The mock runs the same request path, and the box side is shown above.

Accessibility: axe over the open dialog flags only the board's cards behind it (.opacity-70 meta text), which predates this change.

Merge Danger

Door: two-way

The dialog's box is off until ticked. Archiving keeps branches. The box change only refuses earlier what git refused anyway, so a dirty worktree is kept as before, minus its teardown. No migrations.

Blast Radius: worktree-removal

Every non-forced Archive or Remove of a worktree with untracked, non-ignored files now fails at once with git's message, where before it stopped services (and ran the archive script) first. Review worktrees removed by dropWorktree without force get the same check.

🤖 Generated with Claude Code

Stener1 and others added 2 commits October 21, 2026 14:28
Archiving or removing a worktree without force used to stop its services
and run the archive script first, and only then let git refuse a worktree
with uncommitted or untracked files: the teardown ran on work that was
then kept, and the box had already answered "archiving". Now it checks
git status up front and refuses in git's own words, so every Archive path
keeps dirty work before anything is torn down.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Agent Dashboard's Stop and Clean up dialogs get "Archive their
worktrees where it's safe" (remembered, off at first). Ticked, the agents
stop, then each of their worktrees is archived once, through the same
path as the sidebar's Archive…: the archive script runs and the branch is
kept. One with uncommitted changes, with another agent still running in
it or a folder under it, where an agent didn't stop, or on a box that
didn't list its sessions is kept as it is, and its row says why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 21, 2026

Copy link
Copy Markdown

@Stener1 is attempting to deploy a commit to the seanbrydonio's projects Team on Vercel.

A member of the Team first needs to authorize it.

@sean-brydon
sean-brydon merged commit ea12159 into cosscom:main Oct 22, 2026
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants