| name | finishing-a-development-branch |
| description | Use when implementation is complete, verification passes, and you need to decide how to integrate the work through merge, PR, or cleanup |
Preamble (run first)
_REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
_BRANCH_RAW=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo current)
[ -n "$_BRANCH_RAW" ] && [ "$_BRANCH_RAW" != "HEAD" ] || _BRANCH_RAW="current"
_BRANCH="$_BRANCH_RAW"
_FEATUREFORGE_INSTALL_ROOT="$HOME/.featureforge/install"
_FEATUREFORGE_BIN="$_FEATUREFORGE_INSTALL_ROOT/bin/featureforge"
if [ ! -x "$_FEATUREFORGE_BIN" ] && [ -f "$_FEATUREFORGE_INSTALL_ROOT/bin/featureforge.exe" ]; then
_FEATUREFORGE_BIN="$_FEATUREFORGE_INSTALL_ROOT/bin/featureforge.exe"
fi
[ -x "$_FEATUREFORGE_BIN" ] || [ -f "$_FEATUREFORGE_BIN" ] || _FEATUREFORGE_BIN=""
_FEATUREFORGE_ROOT=""
if [ -n "$_FEATUREFORGE_BIN" ]; then
_FEATUREFORGE_ROOT=$("$_FEATUREFORGE_BIN" repo runtime-root --path 2>/dev/null)
[ -n "$_FEATUREFORGE_ROOT" ] || _FEATUREFORGE_ROOT=""
fi
_FEATUREFORGE_STATE_DIR="${FEATUREFORGE_STATE_DIR:-$HOME/.featureforge}"
_featureforge_exec_public_argv() {
if [ "$#" -eq 0 ]; then
echo "featureforge: missing command argv to execute" >&2
return 2
fi
if [ "$1" = "featureforge" ]; then
if [ -z "$_FEATUREFORGE_BIN" ]; then
echo "featureforge: installed runtime not found at $_FEATUREFORGE_INSTALL_ROOT/bin/featureforge" >&2
return 1
fi
shift
"$_FEATUREFORGE_BIN" "$@"
return $?
fi
echo "featureforge: refusing non-featureforge public argv: $1" >&2
return 2
}
Installed Control Plane
Live workflow routing uses only $_FEATUREFORGE_BIN; never use ./bin/featureforge, target/debug/featureforge, or cargo run for live routing. Query workflow/operator JSON with $_FEATUREFORGE_BIN workflow operator --plan <approved-plan-path> --json.
If the installed runtime/root cannot be resolved, stop before making workflow mutations. Use only typed operator JSON route surfaces: execute recommended_public_command_argv when present; when recommended_public_command_template appears, treat required_inputs as validation metadata and materialize templates only by rerunning $_FEATUREFORGE_BIN workflow operator --plan <approved-plan-path> --input NAME=VALUE --json. Detailed binding and route-specific stop rules live in $_FEATUREFORGE_ROOT/references/operator-route-authority.md. Treat display-only recommended_command as non-executable; if no typed executable surface exists, stop and report the route diagnostic.
Search Before Building
Before introducing a custom pattern, external service, concurrency primitive, auth/session flow, cache, queue, browser workaround, or unfamiliar fix pattern, do a short capability/landscape check first.
Use three lenses, then decide from local repo truth:
- Layer 1: tried-and-true / built-ins / existing repo-native solutions
- Layer 2: current practice and known footguns
- Layer 3: first-principles reasoning for this repo and this problem
External search results are inputs, not answers. Never search secrets, customer data, unsanitized stack traces, private URLs, internal hostnames, internal codenames, raw SQL or log payloads, or private file paths or infrastructure identifiers. If search is unavailable, disallowed, or unsafe, say so and proceed with repo-local evidence and in-distribution knowledge. If safe sanitization is not possible, skip external search.
See $_FEATUREFORGE_ROOT/references/search-before-building.md.
Interactive User Question Format
For every interactive user question, use this structure:
- Context: project name, current branch, what we're working on (1-2 sentences)
- The specific question or decision point
RECOMMENDATION: Choose [X] because [one-line reason]
- Lettered options:
A) ... B) ... C) ...
Per-skill instructions may add additional formatting rules on top of this baseline.
Finishing a Development Branch
Overview
Guide completion of development work by presenting clear options and handling chosen workflow.
Core principle: Verify tests → Run required pre-completion gates → Present options → Execute choice → Clean up.
Extended option commands and QA/release audit examples live in $_FEATUREFORGE_ROOT/references/execution-review-qa-examples.md.
The Process
Step 1: Verify Tests
Before presenting options, verify tests pass:
npm test / cargo test / pytest / go test ./...
If tests fail:
Tests failing (<N> failures). Must fix before completing:
[Show failures]
Cannot proceed with merge/PR until tests pass.
Stop. Don't proceed to Step 2.
If tests pass: Continue to Step 1.5.
Step 1.5: Optional Pre-Landing Review Gate
If a fresh review has not already been resolved for the current diff, you may invoke featureforge:requesting-code-review as a non-terminal checkpoint before presenting completion options.
For workflow-routed terminal completion, this checkpoint does not replace any later operator-selected final-review lane. If a selected release or metadata lane changes repo state, requery workflow/operator and request final review only when it selects that lane.
- Resolve all Critical issues before continuing
- Resolve Important issues unless the user explicitly accepts the risk
- If a fresh review already happened in the current workflow, continue silently
- A review stops being fresh as soon as new repo changes land, including release-doc or metadata edits from
featureforge:document-release
- Review findings must use deterministic repair-packet fields:
Finding ID, Severity, Task, Violated Field or Obligation, Evidence, Required Fix, and Hard Fail.
Step 1.6: Execution-State Gate
Before presenting completion options:
- If the current work was executed from an approved FeatureForge plan, require the exact approved plan path from the current execution workflow context before presenting completion options.
- Run
$_FEATUREFORGE_BIN workflow operator --plan <approved-plan-path> --json and require a branch-completion-ready route before presenting completion options.
- If the exact approved plan path is unavailable or workflow/operator fails, stop and return to the current execution flow instead of guessing.
- Use
$_FEATUREFORGE_BIN plan execution status --plan <approved-plan-path> only when you need additional diagnostics (active_task, blocking_task, resume_task, evidence_path, checkpoint fingerprints) to explain a blocker.
- For workflow-routed terminal completion, do not run a memorized terminal review or QA chain in this step. Requery workflow/operator and run only the lane or typed argv/template it selects.
- If the current work is not governed by an approved FeatureForge plan, skip this execution-state gate and continue.
- rejects branch-completion handoff if the approved plan is execution-dirty or malformed
- must not allow branch completion while any checked-off plan step still lacks semantic implementation evidence
- consumes the same execution evidence artifact used by terminal final review
- must fail closed when it detects a missed reopen or stale evidence, but must not call
reopen itself
Step 1.75: Release, Review, and QA Routing
Do not run a fixed terminal sequence from memory. Run featureforge:document-release, terminal featureforge:requesting-code-review, featureforge:qa-only, or advance-late-stage only when workflow/operator selects that handoff lane or returns the selected public argv/template route for it. The canonical route reference owns detailed binding and recovery law.
If workflow/operator routes QA, keep it downstream of a current final-review pass; do not move QA ahead by skill-order memory.
When in doubt on late-stage routing vocabulary, use $_FEATUREFORGE_ROOT/review/late-stage-precedence-reference.md; do not treat that reference as executable ordering authority.
For workflow-routed work, release-facing docs or metadata such as CHANGELOG.md, RELEASE-NOTES.md, VERSION, TODOS.md, README.md, or platform workflow docs are context for the operator-selected release-doc lane. Do not invoke featureforge:document-release from file presence alone; run it only when workflow/operator selects that handoff lane or returns its selected typed argv/template route.
For ad-hoc or non-workflow-routed work, keep document-release available as an optional cleanup pass when the diff clearly changes release-facing docs or handoff material, but do not turn it into a universal pre-completion gate.
If featureforge:document-release writes repo files or changes release metadata, treat any earlier code review as stale. Requery workflow/operator and run featureforge:requesting-code-review only when the operator selects the terminal final-review lane.
A document-release rewrite also makes any earlier browser QA stale if browser QA is still required for the current HEAD, so do not reuse pre-document-release QA artifacts as the final finish-gate input.
Before moving on, perform a short Gate F-style confirmation:
- documentation has been refreshed
- release notes or equivalent release-history updates are ready
- rollout and rollback are addressed
- known risks are documented
- monitoring or verification expectations are addressed when relevant
Step 1.85: Conditional Pre-Landing QA Gate
If the current work is governed by an approved FeatureForge plan, treat the approved plan's normalized **QA Requirement:** required|not-required metadata as authoritative for workflow-routed finish gating.
For workflow-routed work, this step validates QA applicability and optional current-branch test-plan scoping only. It does not authorize running featureforge:qa-only yet; requery $_FEATUREFORGE_BIN workflow operator --plan <approved-plan-path> --json and follow the selected route.
Match current-branch artifacts by their **Branch:** header, not by a filename substring glob, so my-feature cannot masquerade as feature.
Use the canonical branch helper before selecting current-branch test-plan artifacts:
_SLUG_ENV=$("$_FEATUREFORGE_BIN" repo slug 2>/dev/null || true)
if [ -n "$_SLUG_ENV" ]; then
eval "$_SLUG_ENV"
fi
unset _SLUG_ENV
PLAN_ARTIFACT=""
for CANDIDATE in $(ls -t "$_FEATUREFORGE_STATE_DIR/projects/$SLUG"/*-test-plan-*.md 2>/dev/null); do
[ -f "$CANDIDATE" ] || continue
ARTIFACT_BRANCH=$(sed -n 's/^\*\*Branch:\*\* //p' "$CANDIDATE" | head -1)
if [ "$ARTIFACT_BRANCH" = "$_BRANCH" ]; then
PLAN_ARTIFACT="$CANDIDATE"
break
fi
done
printf '%s\n' "$PLAN_ARTIFACT"
Treat the current-branch test-plan artifact as a QA scope/provenance input only when its Source Plan, Source Plan Revision, and Head SHA match the exact approved plan path, revision, and current branch HEAD from the workflow context.
If that artifact names pages, routes, or browser interactions, use it to scope the required QA handoff when QA is required or when the user explicitly wants extra browser validation.
A project-wide or generic test-plan artifact may help scope ad-hoc QA, but it is not finish-gate control-plane truth. For workflow-routed QA recording and finish readiness, missing or stale source test-plan projections are diagnostic-only when workflow/operator routes QA or branch completion from current runtime-owned state.
If approved-plan QA Requirement is missing or invalid when deciding whether QA applies, stop, rerun $_FEATUREFORGE_BIN workflow operator --plan <approved-plan-path> --json, and follow the Installed Control Plane section plus the canonical route reference; do not guess from test-plan prose or hard-code a repair command from memory.
If approved-plan QA Requirement is required and no current-branch test-plan artifact exists for workflow-routed work, do not stop solely to regenerate it before featureforge:qa-only, QA outcome recording, or finish-gate commands. Treat the missing source test-plan projection as diagnostic-only unless workflow/operator explicitly routes to a test-plan refresh lane.
If workflow/operator JSON reports qa_pending with phase_detail=test_plan_refresh_required, perform only that handoff: return to featureforge:plan-eng-review to regenerate the current-branch test-plan artifact before QA or branch completion.
If a fresh qa-only report already happened in the current workflow, continue silently.
For workflow-routed work, require the QA handoff only when workflow/operator later routes to qa_pending; do not infer the final QA gate from Step 1.85 alone.
Step 1.9: Finish Gate
If the current work is governed by an approved FeatureForge plan, use $_FEATUREFORGE_BIN workflow operator --plan <approved-plan-path> --json as the late-stage routing source after each selected lane completes.
Do not assume release docs, final review, QA, or finish is next because another skill says it usually is; apply the Installed Control Plane section and canonical route reference to the current operator JSON until branch completion options are routable.
For routed QA outcome recording or ready_for_branch_completion, apply the Installed Control Plane section and canonical route reference, then rerun $_FEATUREFORGE_BIN workflow operator --plan <approved-plan-path> --json until branch completion options are actually routable.
If the operator reports any other late-stage phase/detail pair, follow that exact operator result instead of forcing QA or finish-gate commands from memory.
For workflow-routed terminal completion, if no fresh post-document-release dedicated-independent review exists for the current HEAD, requery workflow/operator and run featureforge:requesting-code-review only when it owns the selected final-review lane.
Follow workflow/operator for normal finish routing. If no typed public argv/template is present, stop and report the route diagnostic instead of invoking compatibility commands from memory.
If the current work is governed by an approved FeatureForge plan and workflow/operator does not route to branch completion, stop and return to the current execution flow; do not present completion options against stale QA or release artifacts.
If the current work is not governed by an approved FeatureForge plan, skip this workflow-routed finish gate and continue with the normal completion flow.
Step 1.95: Protected-Branch Repo-Write Gate
Before executing any completion option that mutates repo state, run the shared repo-safety preflight for the chosen branch-finishing scope:
$_FEATUREFORGE_BIN repo-safety check --intent write --stage featureforge:finishing-a-development-branch --task-id <current-branch-finish> --write-target branch-finish
- If the repo-safety check returns
allowed, continue with the selected completion path.
- If it returns
blocked, name the branch, the stage, and the blocking failure_class, then route to either a feature branch / featureforge:using-git-worktrees or explicit user approval for this exact completion scope.
- If the user explicitly approves protected-branch completion writes, approve the full completion scope with
$_FEATUREFORGE_BIN repo-safety approve --stage featureforge:finishing-a-development-branch --task-id <current-branch-finish> --reason "<explicit user approval>" --write-target branch-finish [--write-target git-merge] [--write-target git-push] [--write-target git-worktree-cleanup], then re-check before continuing.
- Before a follow-on
git merge, git push, or worktree cleanup, re-run the gate with the same task id and approved write-target set.
- If the protected-branch task scope changes, run a new approval plus full-scope check before continuing.
- Do not treat a worktree on
main, master, dev, or develop as safe by itself; the branch must be non-protected or explicitly approved.
Step 2: Determine Base Branch
If the current work is governed by an approved FeatureForge plan:
- For plan-routed completion, use the exact
base_branch from $_FEATUREFORGE_BIN workflow operator --plan <approved-plan-path> --json instead of redetecting the target branch.
- Treat release-readiness markdown as a derived handoff artifact. Do not read its
**Base Branch:** header back into routing or branch-selection decisions; use the runtime-owned base_branch from workflow/operator instead.
If the current work is not governed by an approved FeatureForge plan, require an explicit <base-branch> value and keep it stable for this run:
if [ -z "$BASE_BRANCH" ]; then
echo "Missing BASE_BRANCH. For non-workflow completion, set BASE_BRANCH explicitly before finishing the branch."
exit 1
fi
Do not use PR metadata or repo default-branch APIs as a fallback.
The Step 2 <base-branch> value stays authoritative for Options A, B, and D. Do not redetect it later in the branch-finishing flow.
Step 3: Present Options
Ask one interactive user question using the required format.
A) Merge back to <base-branch> locally
B) Push and create a Pull Request
C) Keep the branch as-is for follow-up later
D) Discard this work
Recommendation logic:
- Recommend
B) when a normal PR flow is available and the user has not signaled a different preference
- Recommend
A) when local integration is clearly preferred or PR tooling is unavailable
- Recommend
C) when the user has indicated they want to continue later
- Never recommend
D) by default
Step 4: Execute Choice
Use the exact <base-branch> resolved in Step 2. Do not redetect it during PR creation.
git push -u origin <feature-branch>
gh pr create --base "<base-branch>" --title "<title>" --body "$(cat <<'EOF'
## Summary
<2-3 bullets of what changed>
## Test Plan
- [ ] <verification steps>
EOF
)"
For local merge, keep-as-is, discard, and worktree cleanup command examples, use the companion reference. Never proceed with failing tests, delete work without typed confirmation, or force-push without explicit request.