"Multi-issue integration and merge skill - handles post-QA integration of completed worktrees"
Install
npx skillscat add sequant-io/sequant/merger Install via the SkillsCat registry.
Local overrides (read this first). Before following any instruction below, check whether
.claude/.local/skills/merger/overrides.mdexists. If it does, read it and treat its contents as authoritative: its instructions take precedence over anything in this skill they conflict with. This is the supported way to tailor/mergerwithout forking it —overrides.mdlives under.claude/.local/, whichsequant updateandsyncnever overwrite.
Merger Skill
You are the "Merger Agent" for handling post-QA integration of completed worktrees.
Purpose
When invoked as /merger <issue-numbers>, you:
- Capture baseline metrics on main (build errors, test counts)
- Validate QA status for all specified issues
- Detect file conflicts between worktrees
- Generate integration branches for incompatible changes
- Respect dependency ordering
- Clean up worktrees after successful merge
- Run post-merge smoketest with regression comparison against baseline
- Provide detailed merge reports
Recommended Pre-Merge Check
Before running /merger, use sequant merge --check to catch cross-issue gaps at zero AI cost:
sequant run 10 11 12 # implement
sequant merge --check # verify (deterministic checks)
/merger 10 11 12 # merge (this command)sequant merge detects merge conflicts, template mirroring gaps, file overlaps, and residual patterns before /merger attempts the actual merge. See docs/reference/merge-command.md for details.
Usage
# Merge single issue
/merger 10
# Merge multiple issues (detects conflicts, creates integration if needed)
/merger 10 12
# Merge with dependency ordering
/merger 10 12 --order=dependency
# Dry run - show what would happen
/merger 10 12 --dry-run
# Force parallel validation of multiple issues (faster, higher token usage)
/merger 10 12 --parallel
# Force sequential validation (slower, lower token usage)
/merger 10 12 --sequential
# Skip post-merge smoketest
/merger 10 12 --skip-smoketest
# Force merge even if regression is detected (bypasses regression gate)
/merger 10 12 --forceAgent Execution Mode
When processing multiple issues, determine the execution mode for validation checks:
Check for CLI flag override:
--parallel→ Validate all issues in parallel (spawn agents simultaneously)--sequential→ Validate issues one at a time
If no flag, read project settings:
Use the Read tool to check project settings:Read(file_path=".sequant/settings.json") # Parse JSON and extract agents.parallel (default: false)Default: Sequential (cost-optimized)
| Mode | Token Usage | Speed | Best For |
|---|---|---|---|
| Sequential | 1x (baseline) | Slower | Limited API plans, 1-2 issues |
| Parallel | ~Nx (N=issues) | ~50% faster | Unlimited plans, batch merges |
Workflow
Acquire the Checkout Lock (REQUIRED)
/merger runs branch-mutating git in the main checkout: git checkout main
for the baseline in Step 0, then git checkout -b integrate/… and git merge on
the integration path (Step 5), plus the mid-workflow git checkout main in
Steps 6–7. Those verbs are global to the working tree, so before the first one
you must claim the checkout lock (#901), exactly as /fullsolve does in its
Phase 0.3. Without it a session on another issue can interleave a git checkout
and land a merge on the wrong HEAD; and because the guard refuses a non-holder,
an unparticipating /merger is itself refused when someone else holds the tree.
/merger operates on several issues, so identify the holder by the first issue
number passed to it and use that same <first-issue> on the acquire and on
every release below — acquire and release must name the same holder or the
release is refused against your own lock (#906). Substitute the literal number
(e.g. --issue=10 for /merger 10 12); a shell variable is invisible to thepre-tool.sh guard, which reads the command text before the shell expands it.
# Claim the shared working tree before the first branch-mutating verb.
npx sequant locks checkout acquire \
--issue=<first-issue> \
--command="/merger <issue-numbers>" \
--skip-pid-check || true
# Belt-and-suspenders for a parent that launched us with it; the guard's real
# binding comes from watching the acquire command above (#906).
export SEQUANT_ISSUE=<first-issue>--issue is mandatory (#906): it is what proves you are the holder on
release, since the acquiring shell's PID is gone by the next block
(--skip-pid-check). Stale recovery is therefore age-based only (the 6hSEQUANT_SKILL_LOCK_TTL_MS and the 24h SEQUANT_MAX_LOCK_AGE_MS ceiling), not
same-host dead-PID recovery.
Release contract: release the checkout lock —npx sequant locks checkout release --issue=<first-issue> || true — on every
path that exits /merger: happy-path completion (Step 8), the regression-gate
halt (Step 7), and any error/abort in "Error Handling". Do NOT release on a
branch that continues to a later branch-mutating verb (the #906 distinction):
the integration git merge in Step 5 and the git checkout main in Steps 6–7
run under the lock and must stay protected until the run ends.
Orchestrator/MCP mode: when SEQUANT_ORCHESTRATOR is set, every locks checkout action is a no-op (exit 0, no file touched) and the pre-tool.sh
checkout guard stands down, so the acquire/release calls are safe to run
unconditionally.
Step 0: Baseline Capture (REQUIRED)
Purpose: Capture build error count and test pass/fail counts on main before any merge, so post-merge results can be compared to detect regressions.
Skip if: --skip-smoketest flag is set (no comparison needed if smoketest is skipped).
Session caching: If baseline has already been captured in this /merger invocation (e.g., when merging multiple issues), reuse the cached values instead of re-running build and tests.
# Check if baseline is already cached (multi-issue merge scenario)
if [[ -n "$BASELINE_BUILD_ERRORS" && -n "$BASELINE_TEST_FAILURES" ]]; then
echo "♻️ Using cached baseline metrics (captured earlier in this session)"
echo " Build errors: $BASELINE_BUILD_ERRORS"
echo " Test failures: $BASELINE_TEST_FAILURES"
echo " Test passes: $BASELINE_TEST_PASSES"
else
echo "📊 Capturing baseline metrics on main..."
# Ensure we're on main with latest changes
git checkout main
git pull origin main
# 1. Capture build error count
build_output=$(npm run build 2>&1 || true)
BASELINE_BUILD_ERRORS=$(echo "$build_output" | grep -c "error TS" || true)
echo " Baseline build errors: $BASELINE_BUILD_ERRORS"
# 2. Capture test pass/fail counts
test_output=$(npm test 2>&1 || true)
# Parse vitest output format: "Tests X passed | Y failed" or "Tests X passed"
# Use tail -1 to get the Tests line (not Test Files line) from vitest output
BASELINE_TEST_PASSES=$(echo "$test_output" | grep -oE '[0-9]+ passed' | tail -1 | grep -oE '[0-9]+' || echo "0")
BASELINE_TEST_FAILURES=$(echo "$test_output" | grep -oE '[0-9]+ failed' | tail -1 | grep -oE '[0-9]+' || echo "0")
echo " Baseline test passes: $BASELINE_TEST_PASSES"
echo " Baseline test failures: $BASELINE_TEST_FAILURES"
echo "✅ Baseline captured"
fiOutput format (include in merge report):
### Baseline Metrics (main before merge)
| Metric | Count |
|--------|-------|
| Build errors (TS) | $BASELINE_BUILD_ERRORS |
| Test passes | $BASELINE_TEST_PASSES |
| Test failures | $BASELINE_TEST_FAILURES |Step 1: Pre-Merge Validation
For each issue specified:
# Find the worktree for the issue. Resolve by branch (#899/#904) — grepping
# for "feature/$ISSUE" is a prefix match, so ISSUE=89 also hits feature/899-*.
worktree_path=$(npx sequant worktree resolve "$ISSUE") || echo "No worktree for #$ISSUE"
# Check PR status
gh pr list --head "feature/$ISSUE-*" --json number,state,title
# Verify worktree exists and has commits
git -C <worktree-path> log --oneline origin/main..HEADValidation checklist:
- Worktree exists for the issue
- PR exists (or will be created)
- Changes have been committed
- No uncommitted work
Step 1a: Closing-Reference Guard (#1197)
Before merging, check which issues the PR will actually close on merge —
GitHub parses closing keywords anywhere in the body, so this can diverge from
what the PR is supposed to close (a tracker issue mentioned in an AC table,
or a multi-PR issue where only the last PR should close it):
# `gh pr view --json closingIssuesReferences` is not a recognized field on
# gh CLI ≤ 2.66 ("Unknown JSON field") — the REST PR payload doesn't carry
# it either. Query the GraphQL field directly; `{owner}`/`{repo}` resolve
# from the current repo the same way they do in REST `gh api` calls.
gh api graphql -f query='
query($owner:String!,$repo:String!,$pr:Int!){
repository(owner:$owner,name:$repo){
pullRequest(number:$pr){closingIssuesReferences(first:10){nodes{number}}}
}
}' -F owner='{owner}' -F repo='{repo}' -F pr=<PR_NUMBER> \
--jq '.data.repository.pullRequest.closingIssuesReferences.nodes[].number'Work out which issues this PR is allowed to close. In refs mode, or when the
issue carries the no-autoclose label, the answer is none: the PR's own
issue must not close either.
# settings.json is JSONC (`sequant init` writes whole-line // comments), so
# strip those before jq. Only whole-line comments: values such as devUrl
# contain "//".
settings_json='{}'
if [ -f .sequant/settings.json ]; then
settings_json=$(sed -E 's#^[[:space:]]*//.*$##' .sequant/settings.json)
fi
if link=$(printf '%s' "$settings_json" | jq -er '.run.prIssueLink // "closes"') &&
no_close_label=$(printf '%s' "$settings_json" | jq -er '.run.prNoCloseLabel // "no-autoclose"'); then
labels=$(gh api "repos/{owner}/{repo}/issues/<issue-number>" --jq '.labels[].name')
if [ "$link" = "refs" ] || printf '%s\n' "$labels" | grep -qxF "$no_close_label"; then
expected="" # nothing may close
else
expected="<issue-number>" # only the PR's own issue
fi
else
# Fail closed: an unreadable settings file must not quietly mean "closes".
echo "⚠️ Could not parse .sequant/settings.json; treating every closing reference as unexpected." >&2
expected=""
fiStop and report, naming the issue, if the list contains any number not in$expected. In refs/label mode that includes <issue-number> itself; that
is the case this guard exists for:
❌ PR #<PR_NUMBER> closes #<unexpected-number> on merge.
Allowed to close here: #<issue-number> (or nothing, in refs/no-autoclose mode).
Edit the PR body to change that reference to "Refs #<unexpected-number>"
before merging.A list that contains only numbers in $expected (or an empty list) is fine,
so proceed to Step 2.
Step 2: Conflict Detection
Get files changed in each worktree:
# For each worktree
git -C <worktree-path> diff --name-only origin/main...HEADFind overlapping files:
# Compare file lists between worktrees
comm -12 <(sort files_issue1.txt) <(sort files_issue2.txt)Step 3: Conflict Analysis
If overlapping files found:
Semantic analysis: Are the changes compatible?
- Additive changes (new functions) -> likely compatible
- Same function modified -> likely incompatible
- Same file, different sections -> may be compatible
Generate merge preview:
git merge-tree $(git merge-base main branch1) branch1 branch2
Step 4: Resolution Strategy
| Scenario | Action |
|---|---|
| No conflicts | Merge sequentially |
| Compatible changes | Auto-merge with verification |
| Incompatible changes | Generate unified implementation in integration branch |
| True dependency | Enforce merge order |
Step 5: Merge Execution
For clean merges (no conflicts):
# Merge PR first (without --delete-branch to avoid worktree lock conflicts)
gh pr merge <PR_NUMBER> --squash
# Only clean up worktree AFTER merge succeeds
# If merge fails, the worktree is preserved so work isn't lost
#
# Resolve by BRANCH, never by grepping the printed path (#899/#904): the path
# line contains the directory slug, so `grep "feature/$ISSUE"` with ISSUE=89
# also matches `feature/899-...` — and the next line force-removes whatever it
# matched. `worktree resolve` matches the branch's issue number exactly, and
# exits non-zero rather than guessing when nothing (or more than one) matches.
if worktree_path=$(npx sequant worktree resolve "$ISSUE"); then
branch=$(git -C "$worktree_path" rev-parse --abbrev-ref HEAD)
git worktree remove "$worktree_path" --force
git branch -D "$branch" 2>/dev/null || true
fi
# Delete remote branch (previously handled by --delete-branch)
gh api repos/{owner}/{repo}/git/refs/heads/$(gh pr view <PR_NUMBER> --json headRefName --jq '.headRefName') -X DELETE 2>/dev/null || true
# State is tracked by the orchestrator runtime when availableFor conflicting changes (integration branch):
# Create integration branch
git checkout -b integrate/<issue1>-<issue2>-<description> main
# Cherry-pick or merge each worktree's changes
git merge feature/<issue1>-* --no-commit
# Resolve conflicts...
git add .
git commit -m "feat: Integrate #<issue1> changes"
git merge feature/<issue2>-* --no-commit
# Resolve conflicts...
git add .
git commit -m "feat: Integrate #<issue2> changes"
# Run tests on integration branch
npm test
npm run build
# Create integration PR
gh pr create --title "feat: Integrate #<issue1> and #<issue2>" --body "..."Step 6: Post-Merge Verification
After successful merge:
# Pull merged changes to main
git checkout main
git pull origin main
# Verify worktree was cleaned up
git worktree list # Should not show the merged feature branch
# Remote branch is deleted explicitly after merge (see Step 5)
# REQUIRED: Verify state was updated (#305)
# The state should show status="merged" for the issue
# Use the Read tool to check state, then parse JSON
Read(file_path=".sequant/state.json")
# Verify the issue status shows "merged"Step 6a: Worktree Cleanup After Merge (REQUIRED - #305)
After each successful merge, ensure the worktree is removed:
# Find and remove worktree for the issue.
# Resolve by branch, not by grepping the printed path — see the note in the
# clean-merge block above. This one force-removes, so a slug collision here
# destroys an unrelated issue's worktree.
if worktree_path=$(npx sequant worktree resolve "$ISSUE"); then
echo "Removing worktree: $worktree_path"
git worktree remove "$worktree_path" --force
else
echo "No worktree found for #$ISSUE (already cleaned up)"
fi
# Verify worktree removal — resolve must now fail for this issue.
if npx sequant worktree resolve "$ISSUE" >/dev/null 2>&1; then
echo "WARNING: Worktree still exists"
else
echo "✅ Worktree removed"
fiWhy this matters: Leftover worktrees waste disk space and can cause confusion when re-running sequant run on the same issues. The state guard (#305) prevents re-execution, but the worktree should still be cleaned up.
Step 7: Post-Merge Smoketest with Regression Comparison
Skip if: --skip-smoketest flag is set or SEQUANT_MERGER_SKIP_SMOKETEST environment variable is true.
# Check skip flag
if [[ "$SKIP_SMOKETEST" == "true" ]]; then
echo "⏭️ Smoketest skipped (--skip-smoketest flag set)"
# Continue to output report
fiAfter all merges complete and worktrees are cleaned up, verify main is healthy and compare against baseline:
# 1. Ensure we're on main with latest changes
git checkout main
git pull origin main
# 2. Build verification — capture post-merge error count
echo "Running build..."
post_build_output=$(npm run build 2>&1); build_exit=$?
POST_BUILD_ERRORS=$(echo "$post_build_output" | grep -c "error TS" || true)
# 3. Test suite — capture post-merge test counts
echo "Running tests..."
post_test_output=$(npm test 2>&1); test_exit=$?
POST_TEST_PASSES=$(echo "$post_test_output" | grep -oE '[0-9]+ passed' | tail -1 | grep -oE '[0-9]+' || echo "0")
POST_TEST_FAILURES=$(echo "$post_test_output" | grep -oE '[0-9]+ failed' | tail -1 | grep -oE '[0-9]+' || echo "0")
# 4. CLI health check (if sequant CLI is available)
echo "Running CLI health check..."
npx sequant doctor 2>&1 || true
doctor_exit=$?
# 5. Regression comparison against baseline
REGRESSION_DETECTED=false
BUILD_DELTA=$((POST_BUILD_ERRORS - BASELINE_BUILD_ERRORS))
TEST_FAIL_DELTA=$((POST_TEST_FAILURES - BASELINE_TEST_FAILURES))
TEST_PASS_DELTA=$((POST_TEST_PASSES - BASELINE_TEST_PASSES))
if [[ $BUILD_DELTA -gt 0 ]]; then
echo "❌ REGRESSION: $BUILD_DELTA new build error(s) introduced"
REGRESSION_DETECTED=true
fi
if [[ $TEST_FAIL_DELTA -gt 0 ]]; then
echo "❌ REGRESSION: $TEST_FAIL_DELTA new test failure(s) introduced"
REGRESSION_DETECTED=true
fiSmoketest & Regression Output
Report results including regression comparison:
### Post-Merge Smoketest
| Check | Command | Result | Details |
|-------|---------|--------|---------|
| Build | `npm run build` | ✅ PASS / ❌ FAIL | [build output summary] |
| Tests | `npm test` | ✅ PASS (N/N) / ❌ FAIL | [test count or failure summary] |
| CLI Health | `npx sequant doctor` | ✅ PASS / ❌ FAIL / ⏭️ SKIP | [health check output] |
### Regression Check
| Metric | Baseline (main) | Post-merge | Delta | Status |
|--------|----------------|------------|-------|--------|
| Build errors | $BASELINE_BUILD_ERRORS | $POST_BUILD_ERRORS | +$BUILD_DELTA / 0 | ✅ No regression / ❌ REGRESSION |
| Test failures | $BASELINE_TEST_FAILURES | $POST_TEST_FAILURES | +$TEST_FAIL_DELTA / 0 | ✅ No regression / ❌ REGRESSION |
| Test passes | $BASELINE_TEST_PASSES | $POST_TEST_PASSES | +$TEST_PASS_DELTA | ✅ Tests added / ⚠️ Tests removed |
**Regression Result:** ✅ NO REGRESSIONS / ❌ REGRESSIONS DETECTEDRegression Gate
If regressions are detected:
if [[ "$REGRESSION_DETECTED" == "true" ]]; then
if [[ "$FORCE_MERGE" == "true" ]]; then
echo "⚠️ REGRESSION DETECTED but --force flag set. Proceeding with merge."
echo "⚠️ Acknowledgment: Merging despite $BUILD_DELTA new build error(s) and $TEST_FAIL_DELTA new test failure(s)."
else
# Terminal halt — release the checkout lock before stopping (#901/#906).
# This branch does NOT continue to Step 8, so the release lives here.
npx sequant locks checkout release --issue=<first-issue> || true
echo "❌ REGRESSION DETECTED — merge is blocked."
echo ""
echo "New build errors: $BUILD_DELTA"
echo "New test failures: $TEST_FAIL_DELTA"
echo ""
echo "To override this gate, re-run with --force:"
echo " /merger <issues> --force"
echo ""
echo "To investigate:"
echo " npm run build 2>&1 | grep 'error TS'"
echo " npm test -- --verbose 2>&1"
# Do NOT proceed — report regression and halt
fi
fiRegression gate behavior:
| Scenario | --force not set |
--force set |
|---|---|---|
| No regressions | ✅ Proceed | ✅ Proceed |
| New build errors | ❌ Block merge, report | ⚠️ Warn, proceed |
| New test failures | ❌ Block merge, report | ⚠️ Warn, proceed |
| Both | ❌ Block merge, report | ⚠️ Warn, proceed |
Important: The regression gate does NOT trigger automatic rollback. It blocks further action and reports for human decision-making. Use --force only when you've confirmed the regressions are acceptable (e.g., known flaky tests).
Failure Handling (Non-Regression)
If smoketest checks fail but are NOT regressions (same count as baseline), report as pre-existing:
### ℹ️ Pre-existing Failures (not regressions)
| Check | Status | Notes |
|-------|--------|-------|
| Build | ⚠️ $BASELINE_BUILD_ERRORS errors | Same as baseline — pre-existing |
| Tests | ⚠️ $BASELINE_TEST_FAILURES failures | Same as baseline — pre-existing |
These failures existed on main before this merge. They are not caused by the merged PR(s).If smoketest checks fail AND are regressions, report with diagnostic commands:
### ❌ Regressions Detected
| Check | Baseline | Post-merge | New Failures |
|-------|----------|------------|--------------|
| Build errors | $BASELINE_BUILD_ERRORS | $POST_BUILD_ERRORS | +$BUILD_DELTA |
| Test failures | $BASELINE_TEST_FAILURES | $POST_TEST_FAILURES | +$TEST_FAIL_DELTA |
**⚠️ Action Required:**
- Investigate new failures introduced by this merge
- Consider reverting the merge if regressions are critical
- Use `--force` to override if regressions are acceptable
**Diagnostic commands:**
\`\`\`bash
# Investigate new build errors
npm run build 2>&1 | grep "error TS"
# Run failing tests with verbose output
npm test -- --verbose 2>&1
# Check what the merge changed
git log --oneline -3
git diff HEAD~1 --stat
\`\`\`Important: Regression detection does NOT trigger automatic rollback. It reports for human decision-making.
Step 8: Release the Checkout Lock (REQUIRED)
The merge is complete. Release the working-tree lock so other sessions can run
branch-mutating git again (#901). Run this on the happy path — a successful merge
and smoketest, or the --force proceed past a regression. It is the counterpart
to the acquire in "Acquire the Checkout Lock" above.
npx sequant locks checkout release --issue=<first-issue> || trueOn a failure exit instead, the release is done at the halt site — the
regression gate (Step 7) or "Error Handling" — never both, so exactly one release
runs per invocation.
Named-Set Boundary (REQUIRED)
/merger <issue-numbers> is the user's consent to merge exactly those
issues — invoking it is the explicit authorization, the same way sequant merge/sequant merge --watch are explicit and human-triggered (#958's
Non-Goals). That consent does not extend past the named set: never let
Dependency Detection or Stacked PR Detection below pull another issue's PR
into gh pr merge just because it happens to unblock or precede a named one.
Rule: if merge ordering requires a PR whose issue number is not in the
invocation's arg list, halt before merging anything and report it — do not
widen the merge silently, and do not treat the stacked-PR "Continue anyway?
(y/N)" confirmation as license to include an unnamed predecessor. Offer the
widened command for the user to re-run:
❌ Out-of-named-set dependency
#101 depends on #100, but #100 was not in your /merger invocation.
Halting before any merge.
To include it: /merger 100 101This rule governs both sections below.
Dependency Detection
Parse dependencies from issue body or comments:
<!-- In issue body -->
**Depends on**: #10
<!-- Or via label -->
Labels: depends-on/10# Check issue for dependency markers
gh issue view <issue> --json body,labels | jq '.body, .labels[].name'If dependencies found, enforce merge order among the named set. If a
dependency's issue number falls outside the named set, apply the Named-Set
Boundary rule above: halt and report instead of merging it.
Stacked PR Detection (#605)
PRs created with sequant run --stacked have a non-main base and a manifest
line in the body (Part of stack: #N1 → #N2 → ...). They must merge in
order — predecessor first. Merging out of order re-bases the dependent PR's
diff against an unexpected commit and inflates the visible change set.
Detect stacked PRs:
# A PR with a non-main base + manifest is part of a stack
gh pr view <PR_NUMBER> --json baseRefName,body | \
jq -r 'if (.baseRefName != "main" and (.body | contains("Part of stack:"))) then "STACKED" else "STANDALONE" end'Enforce stack order before merging:
- Extract the stack manifest from each PR's body (
Part of stack: #100 → #101 (this) → #102). - Treat the order in the manifest as the merge order — earlier entries land first.
- If every predecessor is in the named set but requested out of order (e.g.
/merger 102 100 101for the stack above), warn before proceeding and recommend the manifest order. - If a predecessor is not in the named set at all (e.g.
/merger 102alone for that stack), the Named-Set Boundary rule applies: halt and report — do not fall through to the "Continue anyway? (y/N)" prompt, since that prompt is for reordering named issues, not for merging an unnamed one. - GitHub auto-updates the dependent PR's base when its predecessor merges, so once the order is correct no manual rebasing is needed.
Warning template:
⚠️ Stack order violation detected
PR #102 is part of stack: #100 → #101 → #102
You requested merge order: #102, #100, #101
Recommended: merge in manifest order to preserve incremental diffs.
Continue anyway? (y/N)Output Format
Merge Report
## Merger Report: Issues #10, #12
### Pre-Merge Validation
| Issue | Worktree | PR | Status |
|-------|----------|-----|--------|
| #10 | feature/10-* | #15 | Ready |
| #12 | feature/12-* | #16 | Ready |
### Conflict Analysis
| File | #10 | #12 | Status |
|------|-----|-----|--------|
| `src/api/route.ts` | Modified | Modified | CONFLICT |
| `src/components/list.tsx` | - | Created | OK |
### Resolution
**Strategy:** Integration branch
**Branch:** integrate/10-12-api-merge
**PR:** #17
### Actions Taken
1. Captured baseline metrics on main
2. Created integration branch from main
3. Merged #10 changes (no conflicts)
4. Merged #12 changes (resolved 1 conflict in route.ts)
5. Tests passed (45 tests)
6. Build succeeded
### Cleanup
- Removed worktree: feature/10-*
- Removed worktree: feature/12-*
- Closed: PR #15, PR #16 (superseded by #17)
### Baseline Metrics (main before merge)
| Metric | Count |
|--------|-------|
| Build errors (TS) | 0 |
| Test passes | 42 |
| Test failures | 0 |
### Post-Merge Smoketest
| Check | Command | Result | Details |
|-------|---------|--------|---------|
| Build | `npm run build` | ✅ PASS | Compiled successfully |
| Tests | `npm test` | ✅ PASS (45/45) | All tests passing |
| CLI Health | `npx sequant doctor` | ✅ PASS | No issues detected |
### Regression Check
| Metric | Baseline (main) | Post-merge | Delta | Status |
|--------|----------------|------------|-------|--------|
| Build errors | 0 | 0 | 0 | ✅ No regression |
| Test failures | 0 | 0 | 0 | ✅ No regression |
| Test passes | 42 | 45 | +3 | ✅ Tests added |
**Regression Result:** ✅ NO REGRESSIONS
### Final Status
**Result:** SUCCESS
**Integration PR:** #17
**Issues to close on merge:** #10, #12Error Handling
Before halting on any failure below, release the checkout lock (#901/#906) —
the acquire in "Acquire the Checkout Lock" claimed the tree, and every failure
here is a terminal exit that must hand it back before stopping:
npx sequant locks checkout release --issue=<first-issue> || trueIf validation fails:
- Report which issues failed validation
- Suggest corrective actions
- Do not proceed with merge
If merge conflicts cannot be resolved:
- Document the conflicts
- Create a draft PR with conflicts marked
- Request manual intervention
If tests fail on integration branch:
- Document failing tests
- Keep integration branch for debugging
- Do not merge
If worktree cleanup fails:
- Log warning but continue
- Manual cleanup may be needed
Configuration
Environment variables:
SEQUANT_MERGER_DRY_RUN- If true, only show what would happenSEQUANT_MERGER_NO_CLEANUP- If true, keep worktrees after mergeSEQUANT_MERGER_FORCE- If true, proceed even with conflicts or regressions (bypasses regression gate)SEQUANT_MERGER_SKIP_SMOKETEST- If true, skip post-merge smoketest (also skips baseline capture)
Output Verification
Before responding, verify your output includes ALL of these:
- Baseline Metrics - Build errors, test passes/failures on main before merge (or "Skipped" if
--skip-smoketest) - Pre-Merge Validation - Status of each issue/worktree/PR
- Conflict Analysis - Table of overlapping files and status
- Resolution Strategy - How conflicts were resolved (if any)
- Actions Taken - Step-by-step log of what was done
- Cleanup Status - Which worktrees/branches were removed
- Post-Merge Smoketest - Build, test, and CLI health results (or "Skipped" if
--skip-smoketest) - Regression Check - Baseline vs post-merge comparison table (or "Skipped" if
--skip-smoketest) - Regression Gate - Whether regressions were detected and what action was taken
- Final Status - SUCCESS/FAILURE with PR link
DO NOT respond until all items are verified.