Skip to content
Development
Command

/phase-5-cleanup

<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios --> <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->

BOOST
From plugin
forgedock
11980 skills80 commands
Install
> /plugin marketplace add RapierCraftStudios/ForgeDock
> /plugin install forgedock@forgedock

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/phase-5-cleanup

Context preview

What this command does when you run it.

<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios --> <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->

Command definition

phase-5-cleanup.md
user-invocable: false
install: core

<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios --> <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->

/orchestrate — Phase 5: Post-Batch Cleanup

> **Skill names**: `{FORGE_SKILL_PREFIX}` is `forgedock:` (plugin install) or empty (`install.sh`), resolved once per run by `commands/work-on.md` § Skill Name Resolution. If the skill is not found under either name, STOP and report "skill not found" — never run the phase inline.

Phase 5: Post-Batch Cleanup

**This phase is MANDATORY after every orchestration batch.** It prevents the rot that accumulates when multiple agents merge PRs in parallel — stale labels, orphaned worktrees, unclosed issues.

Step 5A: Run cleanup sweep

Invoke the `/cleanup` skill with `all` to sweep everything:

Skill(skill="{FORGE_SKILL_PREFIX}cleanup", args="all")

This will:

  • Fix stale workflow labels on any issues the agents left behind
  • Close orphaned open issues whose PRs were merged (common when merging to `staging`)
  • Remove worktrees created by agents in this batch
  • Delete local/remote `fix/*` and `feat/*` branches whose PR has merged — detection uses merged-PR state (`gh pr list --state merged`) as the source of truth, so it covers feature-lane branches merged into a milestone branch as well as squash-merged branches, not just branches merged directly to staging
  • Report milestones that hit 0 open issues — these are ready for `/milestone ship` (staging review + merge). Do NOT close them; closure happens after code reaches staging.
  • Sync Project board state

Step 5B: Run agent audit

Invoke `/audit-agents` on this session to measure pipeline efficiency:

Skill(skill="{FORGE_SKILL_PREFIX}audit-agents", args="latest")

Include the audit summary in the final report (Phase 6). Key metrics to surface:

  • **Avg idle%** — percentage of time agents spent stalled vs working
  • **Resume cycles** — how many times agents had to be resumed
  • **Stall boundaries** — which phase transitions cause the most stalls

Step 5C: Close the coordination issue (claims board) <!-- Added: forge#2072 -->

**Why this step exists**: Step 3D.1 (`phase-3-dependency.md`) creates a per-batch coordination issue (the claims board) and exports `FORGE_COORD_ISSUE`/`COORD_ISSUE_NUMBER`. Step 5A's `/cleanup` orphan sweep (Phase 2A/2B) only closes issues whose PR merged — the claims board has no PR of its own, so that heuristic never matches it; `/cleanup` Phase 2C is the separate safety net that closes boards this step missed. Without this step, one `automation`-labelled issue leaks per orchestration batch.

**Run after Step 5B, before Step 5D.** No-ops cleanly if the claims board was never created this run (`COORD_ISSUE_NUMBER` unset/empty — e.g. Step 3D.1's `gh issue create` failed, or this batch never reached DAG construction). Tolerates GitHub API failures without aborting the rest of Phase 5 — the same tolerant-failure convention (`2>/dev/null || echo ...`, `|| true`) used throughout `phase-3-dependency.md`/`phase-4-execution.md`.

**Orchestrator lease should already be released by this point** (forge#2627): `phase-4-execution.md`'s Termination condition (end of Step 4B) calls `release_orchestrator_lease()` before handing off to Phase 5 on a normal drain, and the "Stopping the orchestrator" procedure (Step 4A-pre.-0.5) does the same on an interrupted exit. Closing the coordination issue here does not depend on lease state either way — an unreleased lease on an issue about to be closed is harmless (a future batch creates its own new coordination issue per Step 3D.1), but if `ACTIVE_CLAIMS_NOTE` logic is ever extended to also surface lease state, prefer checking for a still-unreleased `FORGE:LEASE` the same way `ACTIVE_CLAIMS` is computed above.

**Recover the board when the variable is lost** <!-- Added: forge#3699 -->: `COORD_ISSUE_NUMBER` is a shell variable and does not survive compaction, `--retry` or a fresh-context resume. When it is unset but `BATCH_ID` is known, look the board up on GitHub by the exact `<!-- FORGE:BATCH_ID: ${BATCH_ID} -->` body marker (never a prefix, so another live batch's board is never matched). If `BATCH_ID` is also lost, fall through to the no-op and leave the board to `/cleanup` Phase 2C.

if [ -z "${COORD_ISSUE_NUMBER:-}" ] && [ -n "${BATCH_ID:-}" ]; then
  COORD_ISSUE_NUMBER=$(gh issue list -R {GH_REPO} --state open --label automation --limit 100 \
    --json number,body 2>/dev/null \
    | jq -r --arg marker "<!-- FORGE:BATCH_ID: ${BATCH_ID} -->" \
      '[.[] | select(.body | contains("<!-- FORGE:COORD_ISSUE -->") and contains($marker))] | first | .number // empty' \
      2>/dev/null || echo "")
  [ -n "$COORD_ISSUE_NUMBER" ] && echo "Recovered coordination issue #${COORD_ISSUE_NUMBER} from FORGE:BATCH_ID marker"
fi

if [ -n "${COORD_ISSUE_NUMBER:-}" ]; then
  # Use Step 4A's read_active_claims() helper (re-declare it verbatim here when this
  # phase runs in a fresh context). Releases are separate later comments, so checking
  # for CLAIM_RELEASED inside the claim body would retain every released claim.
  ACTIVE_CLAIMS=$(read_active_claims "$COORD_ISSUE_NUMBER" 2>/dev/null \
    | jq '[.[].holder // "unknown"]' 2>/dev/null || echo '[]')
  ACTIVE_CLAIMS_COUNT=$(echo "$ACTIVE_CLAIMS" | jq 'length' 2>/dev/null || echo 0)

  if [ "$ACTIVE_CLAIMS_COUNT" -gt 0 ] 2>/dev/null; then
    ACTIVE_CLAIMS_NOTE="**Still-active claims at close time** (${ACTIVE_CLAIMS_COUNT}) — not blocking closure, listed for visibility:
$(echo "$ACTIVE_CLAIMS" | jq -r '.[] | "- " + .' 2>/dev/null)"
  else
    ACTIVE_CLAIMS_NOTE="No active (unreleased) claims at close time."
  fi

  # Outcome counters come from Phase 4/6 state; tolerate unset values (default n/a when the orchestrator did not track them).
  MERGED_COUNT="${MERGED_COUNT:-n/a}"; GATED_COUNT="${GATED_COUNT:-n/a}"; FAILED_COUNT="${FAILED_COUNT:-n/a}"

  gh issue close "$COORD_ISSUE_NUMBER" -R {GH_REPO} --comment "Batch comple
Read more
Ships withforgedock

ForgeDock — autonomous AI dev pipeline for Claude Code. GitHub as agent memory: issue in, PR out.

Get the whole plugin

Other commands on forgedock.