--- name: land-merged-pr-with-blocked-tree-ops description: "Use when a merged PR must land in a checkout whose working tree is dirty and workspace policy blocks checkout/stash — prove the delta content-free, hand the operator the two-liner, verify via live config meanwhile." --- Landing a merged PR when the deployment checkout is dirty **and** workspace policy blocks `git checkout`/`git stash`. Use when `git merge --ff-only origin/main` aborts with "Please commit your changes or stash them before you merge" in a SHARED workspace where other agents have work in flight. Earned 2026-10-20 on `dank/command-center` (the checkout IS the deployment). # Land a merged PR with blocked tree ops ## Why it blocks `--ff-only` refuses when **any** incoming path is dirty in the worktree — it checks dirtiness against the *old* HEAD, not whether your content matches the target. Proven: overwriting the file so it is **byte-identical to the target commit** (`cmp` clean against `git show origin/main:`) still aborts with the same message. So "make the file match main" is not a way in, and neither is `git merge` from another worktree (the branch is checked out in the dirty one). The blocking set is what you must know, exactly: ```bash comm -12 <(git diff --name-only HEAD..origin/main | LC_ALL=C sort -u) \ <(git status --porcelain | awk '{print $NF}' | LC_ALL=C sort -u) ``` `LC_ALL=C sort` matters — git's own output order trips `comm: file N is not in sorted order` and you get garbage overlap lists. In the case this was earned on, 12 incoming paths and 57 dirty ones intersected in exactly **one** file. ## Procedure 1. **Fetch, don't merge yet.** List incoming commits (`git log --oneline HEAD..origin/main`) so you can show what is waiting. 2. **Compute the blocking set** with the `comm` above (both inputs `LC_ALL=C sort -u`). 3. **Prove the local delta is content-free**, in the direction that matters — lines the working tree has that `main` does not: ```bash diff <(git show origin/main:) | grep -c '^>' # local-unique lines ``` Zero means the working tree is a strict subset of what was merged: discarding loses nothing. 4. **Preserve before you touch:** copy the current file to `~/.AGENTTRASH/` (snapshot), and copy anything you had moved into a gitignored `.AGENTTRASH/` inside a build worktree to its permanent home in the deployment — otherwise pruning the worktree destroys the only copy of a quarantined page. 5. **Do NOT work around the policy.** `git checkout -- `, `git stash`, and `git stash push -- ` are all blocked in a shared workspace and the block is correct: it protects other agents' in-flight work. Do not reach for `git reset --soft` + `git restore --staged` to slide the pointer past it either — that leaves the index holding staged *reverts* of every incoming path, one careless `git commit -a` away from undoing the merge. 6. **Hand the operator the two-liner** and keep working on what does not depend on it: ```bash git -C ~/.omp checkout -- && git -C ~/.omp merge --ff-only origin/main ``` Say why it is safe (step 3's number, plus where the snapshots live) and what it unblocks. ## Why waiting is not free `scripts/live-sync.sh` merges with a plain `git merge --no-edit origin/main` (its line ~88), so the hourly heartbeat hits the identical wall and raises its ntfy alert `merge conflict with origin/main — local commit kept; needs you at the keyboard`. Report that consequence: the dirt is not merely untidy, it alerts. Also note for later: `git branch -d ` **refuses until the commits reach `main`** — `-d` checks against the current HEAD, not `origin/main` — so local branch deletion goes on the post-landing list, not the pruning list. ## What you CAN do while it waits - **Verify the merged behaviour through the live config, not the branch pointer.** Merged prompt/config changes take effect from the deployment's files: spawn a fresh session/subagent and have it read and quote the changed file back. That proves the change is live even while `main` is behind. - Prune your own build worktrees, but check nothing is running inside them first: `ls -l /proc/*/cwd 2>/dev/null | grep -c "wt/"` (the same guard `live-sync.sh` uses). - Delete the merged remote branches (`git push origin --delete `, allowed on the local Gitea).