Agents Builders

Force remove merged worktrees

Archived
force-remove-merged-worktrees

Created

Jun 22, 19:11

Started

Jun 22, 19:11

Completed

Jun 22, 20:42

DevOps handoff

Type

Feature

Shape

backend

Worktree Slug

force-remove-merged-worktrees

Repositories

mcritchie-studio

Release Train

Branch

feat/force-remove-merged-worktrees

Local URL

QA URL

Production URL

devops worktrees

Acceptance Criteria

  • remove --force overrides content-not-on-release when PR merged
  • Force refuses cleanly if no merged PR found
  • Dirty or unregistered worktrees still block under force

Expected Test Plan

  • unit
  • integration

Checks Run

  • [unit] force_clears_content_blocker? cleared only when force+merged+clean; dirty/no-force never clear (force_decision subprocess load)
  • [integration] run_remove --force end-to-end: merged PR removes, unverified/gh-absent refuses, dirty refuses even merged, no-force unchanged (AGENT_WORKTREE_MERGED_PR + fake-gh injection)

Agent Context

Give bin/agent-worktree remove a MERGE-VERIFIED --force escape hatch. PROBLEM: run_remove (bin/agent-worktree ~L1690) refuses on three blockers — dirty, 'branch content is not represented on <base>' (via cleanup_ready?), and not-git-registered. cleanup_ready?(record) = !dirty && (merged || equivalent_to_main) where :merged is git-ancestry — which SQUASH MERGES break. So worktrees whose PR was squash-merged into main under the old pre-release-branch flow are permanently un-removable (we have 8 such: PRs #76/#82/#83/#85/#86/#89 in mcritchie-studio, #159/#160 in turf-monster — all MERGED on GitHub but content-not-on-origin/release). There is NO override flag today. FIX: add --force to the 'remove' dispatch (parse like --yes at ~L2116: force = ARGV.delete('--force'); pass run_remove(app, task, yes:, force:)). In run_remove, --force SUPPRESSES ONLY the 'content is not represented on <base>' blocker — and ONLY when MERGE-VERIFIED: the branch has a MERGED PR. Verify via gh: the script already has github_repo_slug(dir) (returns owner/repo) and command_available?('gh'); use (a merged PR exists => verified). If --force AND a merged PR is found => clear that blocker, print '✓ <branch> PR #N merged — overriding content guard (--force)', proceed (still respect --yes for the actual teardown). If --force BUT no merged PR / gh unavailable / no github remote => DO NOT remove: keep the blocker + clear message ('--force requires a merged PR; none found for <branch>' or 'gh unavailable'). --force MUST NOT suppress the dirty or not-registered blockers (genuine data-loss / wrong-state — never force those). TESTABILITY (critical — mirror dor-check's DOR_CHECK_CHANGED_FILES injection): make the merged-PR check injectable so tests don't hit real gh — e.g. honor an env override like AGENT_WORKTREE_MERGED_PR (set => treat as merged; ''/unset => not merged) that short-circuits the gh call, OR extract a pure decision method force_clears_content_blocker?(record, force:, merged:) unit-tested directly. Update usage/help (L119) to document remove [--force] [--yes]. TESTS [unit]: the decision — force+merged clears content blocker; force+not-merged does NOT; force NEVER clears dirty or not-registered; no-force unchanged. [integration]: run_remove end-to-end (with the injection) over a temp worktree/record: force+merged removes; force+unmerged refuses; force+dirty refuses. Do NOT change cleanup_ready? semantics for the non-force path, or the reclaim/cleanup flows.

Stage Timeline

Who handled each stage, the time it took (measured), and the model / tokens / cost reported (best-effort) — plus who's on it right now. means the agent didn't report that metric.

  1. Shipped Archived
    Model
    Duration
    Tokens
    Cost
    Completed Jun 23, 17:13 · 4 days ago

Conversation

QA review feedback, agent handoffs, and follow-up notes for this task.

No task feedback has been recorded yet.

Sealed-bid sizing

Edit →

Alex (PM)

Avi (PO)

Dev

Actual