Loop Clean — sweep worktrees of merged PRs
Repo: the lago monorepo root; worktrees in front-worktrees/, slot registry in .worktree-slots.
Scope: the worktree layout only. Runs made with loop-run --in-place (a Conductor workspace, a plain git worktree, a second clone) own no front-worktrees/ entry and are invisible here — their cleanup belongs to whoever owns the checkout, which under Conductor means archiving the workspace. loop-run skips the sweep entirely in that layout; invoked directly from a Conductor workspace, report "nothing to do — in-place layout" and stop.
Steps
List candidates: worktree names from front-worktrees/ starting with a Linear issue ID — pattern ^[A-Z]+-\d+(-.*)?$ (any team prefix, with or without the topic slug suffix, e.g. <TEAM>-<N>-swap-customer-overview-connection). Cross-check .worktree-slots.
Check merge state for each candidate:
gh pr view <name> --repo getlago/lago-front --json state,mergedAt
"state": "MERGED" → cleanup candidate.
"state": "CLOSED" (closed WITHOUT merge — abandoned PR) → candidate too, but flagged separately in the confirmation list as "closed without merge — work was never shipped, destroy anyway?".
"state": "OPEN" or no PR found → NEVER a candidate, skip silently. Pending work is untouchable.
Safety check on each merged candidate — skip WITH a warning if:
- Worktree dirty:
git -C front-worktrees/<name> status --porcelain non-empty (uncommitted work — never destroy it).
- Unpushed commits:
git -C front-worktrees/<name> log origin/<name>..HEAD --oneline non-empty.
Confirm with the operator (ALWAYS — destroy is irreversible: deletes containers, volumes, local branches front+API, all files): show the list of names about to be destroyed plus the skipped ones with reasons. Proceed only on explicit yes.
Destroy each confirmed name, answering the script's own y/N prompt:
printf 'y\n' | lago-worktree destroy <name>
(lago-worktree = front/scripts/lago-worktree.sh if the alias is unavailable.)
Report: destroyed / skipped-with-reason / nothing-to-do.
Hard rules
- NEVER destroy without the operator's explicit confirmation in this session.
- NEVER destroy a dirty worktree or one with unpushed commits — skip and warn instead.
- Only names starting with a Linear issue ID (
^[A-Z]+-\d+): never touch other worktrees (base-app, admin-ui, ...).
- Nothing on the remote is ever touched.
- Two communication registers: messages to humans (chat report, notifications) = short, direct, plain language, no deep-tech jargon. Internal state files (spec.md, review.md, histories, working notes) = written for the AI of a later iteration: dense, precise, full paths/symbols/error strings — optimize for machine effectiveness, not human readability.
1---2name: loop-clean3description: Cleanup phase of the loop pipeline for lago-front, for the `worktree` layout only. Finds local worktrees in front-worktrees/ whose PR is merged and destroys them via lago-worktree destroy, after user confirmation. Use when user says "/loop-clean", asks to clean up merged worktrees, or the loop-run orchestrator runs its sweep step.4---56# Loop Clean — sweep worktrees of merged PRs78**Repo:** the lago monorepo root; worktrees in `front-worktrees/`, slot registry in `.worktree-slots`.910**Scope:** the `worktree` layout only. Runs made with `loop-run --in-place` (a Conductor workspace, a plain `git worktree`, a second clone) own no `front-worktrees/` entry and are invisible here — their cleanup belongs to whoever owns the checkout, which under Conductor means archiving the workspace. loop-run skips the sweep entirely in that layout; invoked directly from a Conductor workspace, report "nothing to do — in-place layout" and stop.1112## Steps13141. **List candidates**: worktree names from `front-worktrees/` starting with a Linear issue ID — pattern `^[A-Z]+-\d+(-.*)?$` (any team prefix, with or without the topic slug suffix, e.g. `<TEAM>-<N>-swap-customer-overview-connection`). Cross-check `.worktree-slots`.15162. **Check merge state** for each candidate:1718 ```bash19 gh pr view <name> --repo getlago/lago-front --json state,mergedAt20 ```2122 - `"state": "MERGED"` → cleanup candidate.23 - `"state": "CLOSED"` (closed WITHOUT merge — abandoned PR) → candidate too, but flagged separately in the confirmation list as "closed without merge — work was never shipped, destroy anyway?".24 - `"state": "OPEN"` or no PR found → NEVER a candidate, skip silently. Pending work is untouchable.25263. **Safety check** on each merged candidate — skip WITH a warning if:27 - Worktree dirty: `git -C front-worktrees/<name> status --porcelain` non-empty (uncommitted work — never destroy it).28 - Unpushed commits: `git -C front-worktrees/<name> log origin/<name>..HEAD --oneline` non-empty.29304. **Confirm with the operator** (ALWAYS — destroy is irreversible: deletes containers, volumes, local branches front+API, all files): show the list of names about to be destroyed plus the skipped ones with reasons. Proceed only on explicit yes.31325. **Destroy** each confirmed name, answering the script's own y/N prompt:3334 ```bash35 printf 'y\n' | lago-worktree destroy <name>36 ```3738 (`lago-worktree` = `front/scripts/lago-worktree.sh` if the alias is unavailable.)39406. **Report**: destroyed / skipped-with-reason / nothing-to-do.4142## Hard rules4344- NEVER destroy without the operator's explicit confirmation in this session.45- NEVER destroy a dirty worktree or one with unpushed commits — skip and warn instead.46- Only names starting with a Linear issue ID (`^[A-Z]+-\d+`): never touch other worktrees (base-app, admin-ui, ...).47- Nothing on the remote is ever touched.48- **Two communication registers**: messages to humans (chat report, notifications) = short, direct, plain language, no deep-tech jargon. Internal state files (spec.md, review.md, histories, working notes) = written for the AI of a later iteration: dense, precise, full paths/symbols/error strings — optimize for machine effectiveness, not human readability.