| name | ai-branch-cleanup |
| description | Cleans branches safely: switches to the default branch, prunes merged and squash-merged branches, syncs to remote, sweeps stale specs, rotates `.ai-engineering/runtime/` per retention policy. Trigger for 'tidy up', 'tidy branches', 'sync to main', 'delete old branches', 'start fresh', 'rotate runtime'. Auto-invoked by /ai-pr after merge. Not for committing changes; use /ai-commit instead. Not for code-level dead-code removal; use /ai-simplify instead. |
| effort | cheap |
| argument-hint | --branches|--sync|--specs|--runtime|--consolidate-spec <slug>|--all |
| tags | ["git","branch","cleanup","hygiene","status","delivery"] |
| requires | {"bins":["git"]} |
| model_tier | haiku |
| mirror_family | antigravity-skills |
| generated_by | ai-eng sync |
| canonical_source | .claude/skills/ai-branch-cleanup/SKILL.md |
| edit_policy | generated-do-not-edit |
Branch Cleanup
Full repository hygiene: safely migrate to the default branch, delete merged and squash-merged branches, sweep stale specs, rotate runtime artifacts, and produce a per-branch status report. No destructive operations without confirmation.
Quick start
/ai-branch-cleanup # full: instinct consolidation + sync + branch cleanup + spec sweep + runtime rotate + report
/ai-branch-cleanup --sync # sync to default branch only
/ai-branch-cleanup --branches # branch cleanup only (no migration)
/ai-branch-cleanup --specs # spec lifecycle sweep + _history.md rotation (DRAFT >14d → ABANDONED; SHIPPED → row appended)
/ai-branch-cleanup --runtime # rotate .ai-engineering/runtime/ per retention policy
/ai-branch-cleanup --consolidate-spec <slug> # manual spec consolidation via _shared/consolidate-spec.md
/ai-branch-cleanup --all # explicit full cleanup
Process
Default (no flags) ≡ --all: runs Phase 0a → 0 → 1 → 3 → 4 → 5 → 2. Single-purpose flags run only their phase.
Phase 0a — Instinct consolidation (default / --all, fail-open)
- Consolidate session learnings BEFORE switching branches: if
.ai-engineering/observations/observations.yml exists, run /ai-session-watch --review to fold this session's observations (especially the LLM-only corrections family) into the corpus — closing the no-commit/no-PR gap where a tidy-up ends a session that never ran --review. Skip silently when the file is absent (fail-open) or when a single-purpose flag (--branches/--sync/--specs/--runtime/--consolidate-spec) ran without --all. Mirrors /ai-pr Step 2 and /ai-commit Step 2.
Phase 0 — Safe migration (--sync or --all)
- Detect default branch —
git symbolic-ref refs/remotes/origin/HEAD (main or master).
- Record current branch for the report.
- Auto-stash if dirty —
git stash push -m "cleanup-auto-stash-$(date +%s)".
- Switch to default —
git checkout <default>.
- Pull latest —
git pull --ff-only origin <default>. If ff-only fails: WARN and STOP.
- Restore stash —
git stash pop. On conflict: WARN, leave stash, continue cleanup.
Phase 1 — Branch analysis (--branches or --all)
- Fetch and prune —
git fetch --prune origin.
- Enumerate all local branches (excluding
main, master).
- Classify each branch:
| Category | Criteria | Action |
|---|
| Merged | In git branch --merged <default> | Delete (git branch -d) |
| Squash-merged | Not in --merged but git diff <default>..<branch> is empty | Delete (git branch -D) |
| Gone (safe) | Tracking ref [gone] AND no content diff | Delete (git branch -D) |
| Gone (has dev) | Tracking ref [gone] BUT has content diff | KEEP |
| Active | Has remote tracking, not merged | KEEP |
| Local only | No remote, has commits ahead | KEEP |
- Delete eligible — merged with
-d, squash-merged and gone-safe with -D.
Phase 3 — Spec sweep (--specs or --all)
Reap stale spec drafts so the lifecycle ledger does not accumulate abandonware. Run python .ai-engineering/scripts/spec_lifecycle.py sweep: DRAFTs older than 14 days move to ABANDONED; counts are returned as JSON and emitted as a framework_operation audit event. Fail-open: a missing script or locked sidecar logs and continues — branch cleanup is the load-bearing hot path.
Phase 4 — Runtime rotation (--runtime or --all)
Rotate .ai-engineering/runtime/ so transient observability data does not bloat the working tree. Run python .ai-engineering/scripts/runtime_rotate.py:
| Subtree | Retention | Action |
|---|
runtime/tool-outputs/*.txt | 7 days | unlink |
runtime/autopilot/sub-* | 30 days | rmtree |
runtime/tool-history.ndjson | 10000 lines / 5 MB | tail-truncate |
Hot-path budget <100 ms; stdlib only; idempotent; fail-open on missing dirs; emits a runtime-rotate framework_event per run.
Phase 5 — Spec consolidation (--specs or --all)
ai-eng cleanup specs runs both verbs in order: reconcile_merged then consolidate_shipped. The composite phase ORDER is unchanged (the D-161-04 fix is gh-aware classification, NOT resequencing).
- Reconcile (
python .ai-engineering/scripts/spec_lifecycle.py reconcile_merged, the D-153-03 backstop): for any non-terminal sidecar (DRAFT/APPROVED/IN_PROGRESS), classify merge state primarily via gh PR state (gh pr list --head <branch> --state merged) — this SURVIVES the Phase-1 branch prune; the local-ref check (git branch --merged + squash-merge emptiness) is the FALLBACK when gh is absent. On a merged classification, resolve the PR via gh and call mark_shipped — catching specs merged via the GitHub UI that /ai-pr never marked, including those whose local branch Phase 1 already deleted.
- Consolidate (
python .ai-engineering/scripts/spec_lifecycle.py consolidate_shipped): append the canonical 7-col _history.md row for any SHIPPED record (including ones reconcile just marked) and emit the framework_operation audit event.
Verification-only step — actual lifecycle writes live in spec_lifecycle.py; this skill calls the entry point. Idempotent: already-SHIPPED records are a no-op. Fail-open: missing script or locked sidecar logs and continues. See .agents/skills/_shared/consolidate-spec.md for the shared handler; the --consolidate-spec <slug> flag exposes the explicit post-merge action via spec_lifecycle.py mark_shipped.
Phase 2 — Status report
- Build per-branch table:
## Repository Cleanup Report
**Default branch**: `main` (up to date)
**Previous branch**: `feat/old-feature`
**Working tree**: clean | stash restored | stash pending
| Branch | Action | Reason | Remote | Ahead/Behind |
|--------|--------|--------|--------|--------------|
| `feat/done` | DELETED | Merged | -- | -- |
| `feat/squashed` | DELETED | Squash-merged | -- | -- |
| `feat/active` | KEPT | Unmerged (5 commits) | origin/feat/active | +5/-2 |
Phase 6 — Spec consolidation (--consolidate-spec <slug>)
Read .agents/skills/_shared/consolidate-spec.md and execute the shared handler: resolve the spec record, append/upsert the _history.md row via spec_lifecycle.py mark_shipped, clear .ai-engineering/specs/spec.md and plan.md to placeholders. Fail-open on missing script.
Examples
User: "tidy up before I start a new task"
/ai-branch-cleanup
Switches to main, ff-pulls, prunes merged + squash-merged branches, sweeps stale spec drafts, rotates runtime, prints the per-branch report.
Integration
Called by: /ai-pr (auto after merge), /ai-start (session bootstrap). Calls: /ai-session-watch --review (Phase 0a, fail-open instinct consolidation), git, python .ai-engineering/scripts/spec_lifecycle.py sweep, python .ai-engineering/scripts/runtime_rotate.py. See also: /ai-brainstorm (run before new spec), /ai-simplify (code-level cleanup).
References
.ai-engineering/manifest.yml — protected branch rules.
.agents/skills/ai-brainstorm/SKILL.md — spec creation composes cleanup.
$ARGUMENTS