From Tandem
Close out a whole phase after an execution-strategist chat / execute-batch run finishes — gate on every phase story being done, compile a phase retrospective, capture follow-ups, update the board, then run a gated merge to main. Use when the user asks to close a phase, wrap up a phase, finish a batch/chat, run a phase retro, or integrate a finished phase.
How this skill is triggered — by the user, by Claude, or both
Slash command
/Tandem:close-phaseThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Operate as **PM hat**. `close-phase` is the **phase-level analogue of `close-out-story`**: where
Operate as PM hat. close-phase is the phase-level analogue of close-out-story: where
close-out-story is the per-story Definition-of-Done gate, this is its per-phase counterpart —
invoked after an execution-strategist chat / execute-batch run finishes, to wrap a whole
phase up safely and integrate it.
Opener counterpart:
start-phaseis the opener this skill closes against.start-phaseopens a phase — it cuts the phase branchphase/<phase-id>offmainper the shared phase-branch convention (recorded in40-Decisions/, ADR-0045);close-phasecloses that same phase — it merges that branch back tomain(Steps 6–7). Both skills obey the one branch convention, so the branch the opener creates is exactly the one the closer merges.
It runs in a fixed order, each step gated on the one before it:
done, or abort and list the gaps.MONITOR.md, regenerate the dashboard.main — integrate only when the merge gate passes; never force-merge.Dry-run-until-gated. Steps 3–5 only read and append artefacts; the merge step is hard-gated and never force-merges (see "Integration"). If the done-gate fails, the skill stops and reports — it never partially wraps up an incomplete phase.
Take an explicit phase / chat / epic target from the user — never infer which phase to close from ambient state. Accepted targets:
CHAT-02) from an EXECUTION-STRATEGY-*.json
sidecar — resolve to the stories[] listed under that chat / phase;EPIC-NN (or a single FEAT-NN.M) — resolve the set of stories belonging to that
epic / feature by globbing 32-Stories/EPIC-NN/....Resolve the set of stories in the target phase before doing anything else, then echo the resolved list (id + status) back to the user so the scope is explicit and reviewable. If the target is ambiguous, missing, or resolves to zero stories, stop and ask for a concrete phase / chat / epic — do not guess which stories are in scope.
done)Verify every resolved phase story is status: done. This is a hard gate:
done → proceed to the retrospective (Step 3).done → abort and list the not-done stories (each id + its current
status), so the operator knows exactly which stories still block the close. Do not compile
a retro, capture follow-ups, update the board, or merge for an incomplete phase.This mirrors close-out-story's gate-then-act discipline at the phase level: the gate is
non-negotiable, and the abort-and-list path is the load-bearing behaviour — a half-closed phase
is worse than an un-closed one.
Once the done-gate passes, compile a phase retrospective — derived from the phase's own
artefacts (its stories, their paired testplans, and the 34-Bugs/ + 40-Decisions/ filed
during the phase), never invented from memory. Three parts:
done stories and the PASS results of their paired
testplans (the TCs that verify each story). One line per story: what it delivered.34-Bugs/), ADRs created (40-Decisions/), and the execution lanes used (the
serial / parallel lanes from the execution-strategist strategy this phase ran under).Because every part is sourced from the phase artefacts — the stories' and testplans' statuses
and results, the bugs and ADRs filed in the phase — the retro is reproducible and auditable, not a
subjective recollection. This is phase-cadence, distinct from the time-cadence retros
(weekly-monitor / monthly-retro): it closes one phase, not a calendar window.
Before touching the board, sweep the phase for loose ends and capture them so nothing surfaced during the work is lost:
11-Backlog/BACKLOG-NNNN-<slug>.md, from
91-Templates/BACKLOG.template.md). This mirrors reflect / refine-backlog: a follow-up that
isn't filed is a follow-up that's lost.40-Decisions/ADR-NNNN-<slug>.md) as a backstop, so the phase's
decisions are all on record before the phase closes.Write the phase up and refresh the live board:
41-Reports/PHASE-<phase-id>-<YYYY-MM-DD>.md (the home is fixed by a
recorded ADR — see "Recorded decisions" below).42-Monitor/MONITOR.md: a phase summary plus a one-line revision-history
entry dated today.npm run pm:dash so 42-Monitor/DASHBOARD.html reflects the
closed phase.The skill's name + phase-granularity and the phase-report home are settled once in an ADR
(40-Decisions/), not re-litigated each phase. The home choice is 41-Reports/PHASE-* (the
phase report is a generated execution artefact alongside EXECUTION-STRATEGY-*), rather than
14-Retros/ (reserved for the time-cadence weekly/monthly retros).
main (gated)The integration step runs after the wrap-up — the retro, follow-up capture, and board update
(Steps 3–5) all happen first; only then does the phase merge to main.
Before evaluating the merge gate, detect whether the phase branch has already been merged
to main — the real order of events sometimes runs ahead of the board (this kit hit exactly this:
a phase branch was fast-forwarded into main in git while the board still said "merge pending").
Probe true ancestry, not a clean working tree:
git merge-base --is-ancestor phase/<phase-id> main && echo "ALREADY-MERGED" || echo "NOT-MERGED"
git merge-base --is-ancestor phase/<phase-id> main exits 0 — the phase
branch tip is reachable from main): route to the retro-only path. Steps 2–5 (done-gate,
retrospective, follow-up capture, board + MONITOR + dashboard) still run in full; only the
merge itself (Step 6 gate + Step 7 mechanism) is skipped and marked already-integrated in the
phase report and the MONITOR revision-history line (e.g. "merge: already-integrated — phase branch
is an ancestor of main"). Nothing is force-merged or re-merged; the retro + board update are the
whole job.--is-ancestor exits non-zero): the normal path — fall through to the
merge gate (below) and Step 7.Gate on true ancestry, never on a clean tree. --is-ancestor is true only when the phase
branch tip is fully reachable from main; a partially-merged branch (some commits in main,
tip not yet) returns non-zero and therefore takes the normal merge path — a partial merge must
not be mistaken for a complete one. A clean working tree alone says nothing about whether the
phase was integrated, so it is not the signal used here.
On the not-merged (normal) path, before anything reaches main, a hard merge gate must
pass — all four items:
done — re-confirm the Step-2 gate still holds for every story in the phase.npm run pm:lint green — the PM artefacts validate.PROJECT-CONTEXT.md's quality
commands (scoped to the area the phase changed).git status --porcelain is empty (no uncommitted changes).If any gate item is unmet, the skill refuses to merge and reports which item failed — it does not proceed. A blocked merge names the failing gate item so the operator knows exactly what to fix; it never merges a phase that hasn't cleared all four.
Once the merge gate (Step 6) passes, integrate via one of two mechanisms — never a force-merge:
phase/<phase-id> — the branch start-phase cut off main per the shared convention,
ADR-0045) to main and surface the PR command / link for the operator to review and merge.main is allowed,
but only once the Step-6 gate has passed.In both cases the skill surfaces the PR / merge command or link rather than force-merging — it
never force-merges and never bypasses the gate. No gh CLI is assumed: surface a
copy-pasteable command or link; don't hard-call a host API. The PR-vs-gated-direct default and the
gate composition are recorded in an ADR (40-Decisions/) so the integration path is settled once.
10-Inbox/APPROVALS.md)A merge to main is a manual, gated approval — when the operator confirms it (the gated
direct merge, or merging the surfaced PR), append a one-line approval entry to
10-Inbox/APPROVALS.md so the sign-off survives beyond the chat transcript (audit + handover).
The same applies on the already-integrated retro-only path (Step 6a): record that the close was
confirmed even though no fresh merge ran. Append (newest at the bottom):
- <ISO 8601 timestamp> — <what was approved> — by: <who> — gated: <artefact / command>
e.g. - 2026-06-06T15:55:00+01:00 — merge phase/p1-outcome-contract to main — by: operator — gated: close-phase Step 7 (gated direct merge).
10-Inbox/ is not a linted artefact folder, so the
entry must keep the file valid plain markdown.10-Inbox/APPROVALS.md does not exist yet, create it (header + the convention
documented at the top of that file) and append the first entry. See the file for the full
convention.close-out-story.npm run pm:dash).A closed phase means the active frame's work is done. Always reset:
node _00-Project-Management/93-Scripts/mode.js set neutral --by auto-neutral --session <session_id>
Announce it: "Phase closed — Tandem mode reset to Neutral." This is also how dual
returns to Neutral. Use the session ID from the session context.
npx claudepluginhub data-ai-xyz/tandem --plugin TandemGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.