agentsclimarketplace

Rebase validate

Skill voxpelli/claude-git/skills/rebase-validate

Git workflow safety skills for rebase validation, merge auditing, and stacked PR management

Install
npx -y skills add voxpelli/claude-git --skill rebase-validate

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Validates git rebase correctness using a five-layer pipeline (range-diff, sem, weave, jscpd, tests). Use when verifying a git rebase (especially stacked PRs with --update-refs), comparing branches post-rebase, or auditing conflict resolution correctness. Covers scenarios like: 'validate rebase', 'check rebase', 'did we lose anything', 'compare before and after rebase', 'duplicate test blocks', 'rebase validation', 'run range-diff', 'lost code during rebase', 'rebase artifacts', 'conflict resolution verification'.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

14.3 KB, ~3.6k tokens by cl100k_base, as published. Nobody here has run it

Rebase Validation — Five-Layer Pipeline

Validate a git rebase for lost code, duplicate blocks, broken refs, and stale references using five complementary layers. No single tool catches all rebase regressions — the value is in layered defense.

When to Use

  • After completing any rebase with conflict resolution
  • After git rebase --update-refs on a stacked branch set
  • When comparing a rebased branch against the original
  • When the user suspects code was lost or duplicated during rebase

Quick Start

If the user just finished a rebase and wants validation, run this sequence:

Step 0: Verify refs (are we comparing the right things?)
Step 1: git range-diff -s (commit overview — seconds)
Step 2: sem entity-level diff — MCP (mcp__sem__sem_diff) or CLI, if available
Step 3: weave preview target (merge readiness — if weave is available)
Step 4: jscpd + duplicate grep (token-level — catches what sem misses)
Step 5: project validation suite (functional oracle)

Always run Step 0 first. After Step 0 completes, Steps 1-4 can run as parallel agents. Step 5 is the final oracle. On agents without a parallel-Agent tool, run Steps 1-4 sequentially — they're independent.

Step 0: Verify Refs

Before ANY comparison, confirm refs point where expected. A broken ref makes every subsequent comparison meaningless.

# Confirm branch positions
git rev-parse --short <rebased-branch>
git rev-parse --short <original-branch>

# Confirm ancestry
git merge-base --is-ancestor <expected-base> <rebased-branch> && echo "OK" || echo "WRONG BASE"

Why this matters: git rebase --update-refs silently moves ALL branch refs pointing to commits in the replayed range — including backup branches. If you created a backup before rebase and it was in the replayed range, it got moved.

Safe backup strategy: use tags (not branches) for pre-rebase snapshots, or create backup branches pointing to commits OUTSIDE the range being replayed.

Optional safety check — if no pre-rebase snapshot exists, git reflog can show where the branch pointed before rebase:

git reflog <rebased-branch> | head -5

Step 1: git range-diff -s (Commit-Level)

The single most important first check. Gives a complete overview in seconds.

# Using remote as "before" snapshot (most practical if pushed before rebase)
git range-diff -s origin/old-branch..origin/old-tip  new-base..new-tip

# Using pre-rebase tags
git range-diff -s pre-rebase/branch..old-tip  new-base..new-tip

# Immediately after rebase (reflog — only works for the tip branch)
# Assumes @{u} has not moved since the rebase (e.g. no force-push to upstream)
git range-diff @{u} @{1} @

Reading the output

SymbolMeaningAction
=Identical patchNo review needed
!Altered (conflict resolution changed content)Review these
<Dropped (only in old range)Verify intentional
>Added (only in new range)Verify expected

Use --creation-factor=90 for rebases with heavy conflict resolution — the default (60) can misclassify heavily-resolved commits as drop+add instead of altered. The algorithm builds a cost matrix via "diff of diffs" and solves least-cost assignment — higher creation-factor values make it more forgiving of large changes when pairing commits.

Additional useful flags:

  • --left-only — suppress commits missing from the old range (show only what's new or changed)
  • --right-only — suppress commits missing from the new range (show only what was dropped or changed)

Note: range-diff ignores merge commits by default. This is correct for rebases (which linearize history) but matters if comparing branches that contain merges.

For a quick count:

git range-diff -s ... | grep -c '='   # identical
git range-diff -s ... | grep -c '!'   # altered (review these)
git range-diff -s ... | grep -c '<'   # dropped
git range-diff -s ... | grep -c '>'   # added

Step 2: Entity-Level Diff (sem MCP or CLI)

Compares named code entities between branches. See references/silent-behaviors.md for limitations (incl. the MCP/CLI field-name difference). Prefer the most capable backend available, in the order below. On a large diverged branch, scope to the suspect files (e.g. file_path on the MCP tool, or a -- <path> pathspec on the CLI) — a whole-branch diff is the 900-entity noise trap.

Tier 1 — sem MCP (preferred when available). Call mcp__sem__sem_diff with base_ref = old-branch and target_ref = new-branch (optional file_path to scope). If the tool is not present in this session or the call errors, do not retry — fall through to Tier 2. It returns JSON shaped:

{ "changes": [ { "change_type": "added|modified|deleted|renamed",
                 "entity_name": "...", "entity_type": "...", "file": "..." } ],
  "total_changes": N }

For risk-ranking a large change set, mcp__sem__sem_impact (file_path + entity_name, mode=all) surfaces the highest-fan-in changed entity to direct attention first (see the Agent Delegation Pattern below).

Tier 2 — sem CLI (fallback). Emit an explicit signal when sem is absent so a silent no-op is never mistaken for "ran clean":

if command -v sem >/dev/null 2>&1; then
  sem diff --format json old-branch..new-branch
  # Alternative syntax if dotdot doesn't work:
  # sem diff --from old-branch --to new-branch --format json
else
  echo "sem CLI not installed — Tier 2 did NOT run; fall through to Tier 3" >&2
fi

As of sem 0.6.0: the CLI emits camelCase (changeType, filePath); the MCP emits snake_case (change_type, file). The summarizer below handles both.

Tier 3 — git (NOT an entity-level check). If neither MCP nor CLI is available, git diff --stat gives a file/line summary — but it cannot see a function dropped from an otherwise-present file. Record Layer 2 as unavailable (not passed) in your final summary and lean harder on Steps 4–5:

git diff --stat old-branch new-branch

Summarize by change type and file. MCP path: you already hold the structured JSON — read the change_type/file counts directly; no shell needed. Apply the same guards the script enforces below: if the result has no changes array, or a record lacks both change_type and file, treat it as schema drift and do NOT report zero. Then apply the zero-result check below. CLI path: pipe through the script, which normalizes both field shapes and fails loud rather than reporting a false zero:

sem diff --format json old-branch..new-branch | python3 -c "
import json, sys, collections
data = json.load(sys.stdin)
changes = data.get('changes')
if not isinstance(changes, list):
    sys.exit('Step 2: no usable changes[] — sem produced no entity diff; do NOT read as zero changes')
ct = lambda c: c.get('change_type') or c.get('changeType')
fp = lambda c: c.get('file') or c.get('filePath')
if any(ct(c) is None or fp(c) is None for c in changes):
    print('  WARNING: records with unrecognized fields — possible sem schema drift; counts may be wrong', file=sys.stderr)
by_type = collections.Counter(ct(c) for c in changes)
by_file = collections.Counter(fp(c) for c in changes)
for t, n in by_type.most_common(): print(f'  {t}: {n}')
print()
for f, n in by_file.most_common(15): print(f'  {n:3d} {f}')
"

Focus on deleted entities (backup has, rebased doesn't) — with base_ref = old-branch and target_ref = new-branch, a backup-only entity surfaces as deleted. These are potential losses; filter out intentionally deleted files before investigating.

A zero/empty result does not clear test files or large files. sem silently yields no entities for describe()/it()/test() blocks (call expressions) and for files over the 32KB tree-sitter cap (see references/silent-behaviors.md). When the change touches test files or files >30KB, treat a sem zero as inconclusive and defer to Step 4 (jscpd + grep) before declaring no losses.

Step 3: weave preview (Merge Readiness)

After a successful rebase onto target, this should show 0 conflicts.

weave preview target-branch

If conflicts remain, the rebase didn't fully resolve all divergences. This is normal if target has commits not yet in the rebased branch.

Check availability first:

command -v weave >/dev/null 2>&1 || echo "weave not installed — skipping to Step 4"

Step 4: Duplicate Detection (Token-Level)

This layer catches what sem/weave miss — they cannot parse ~40% of test files.

4a: jscpd for duplicate code blocks

npx --yes jscpd . --ignore "node_modules/**,dist/**,.git/**" --min-lines 5 --min-tokens 50 --max-lines 5000 --reporters console

CRITICAL: --max-lines defaults to 1000 — files over 1000 lines are silently skipped. Always pass --max-lines 5000.

Compare clone count against baseline (if available) to distinguish pre-existing from rebase-introduced duplicates.

4b: Duplicate test name grep

# Adapt the find path to match the project's test directory layout
while IFS= read -r -d '' f; do
  dupes=$(grep -oE "(it|test)\(['\"\`][^'\"\`]*['\"\`]" "$f" | sort | uniq -d)
  [ -n "$dupes" ] && echo "DUPLICATE in $f:" && echo "$dupes"
done < <(find . -path ./node_modules -prune -o \( -name '*.spec.js' -o -name '*.test.js' \) -print0 2>/dev/null)

node:test silently runs both copies of duplicate it() blocks — no warning. Cross-scope duplicates (same name in different describe() blocks) are usually intentional. Same-scope duplicates are bugs.

4c: ast-grep for structural patterns (optional)

If ast-grep is installed (brew install ast-grep), it can complement jscpd with structural pattern matching — finding code that matches a known shape rather than detecting unknown duplicates:

command -v sg >/dev/null 2>&1 || echo "ast-grep not installed — skipping"

# Find all test blocks (useful for manual review of test structure)
sg -p 'it($NAME, $$$BODY)' -l js .

# Find all describe blocks wrapping test blocks
sg -p 'describe($NAME, $$$BODY)' -l js .

ast-grep is a search tool, not a clone detector — it finds known patterns, while jscpd finds unknown duplicates. Use ast-grep when you know what rebase artifact to look for. No silent file-size thresholds (unlike jscpd).

Step 5: Functional Verification

The definitive oracle. Every other layer is advisory.

Run the project's full validation suite — lint, type checking, and tests. Adapt these commands to the project's setup:

# Example (adapt to your project)
npm run check       # or: cargo check, go vet, etc.
npm test            # or: cargo test, go test ./..., etc.

Duplicate test blocks pass both lint and tests — they are invisible to this layer. That's why Layer 4 exists.

Baseline Establishment (Before Rebase)

If you haven't rebased yet, run these first to establish a baseline:

# Save baseline duplicate counts (adapt paths to project layout)
npx --yes jscpd . --ignore "node_modules/**,dist/**,.git/**" --min-lines 5 --min-tokens 50 --max-lines 5000 --reporters console > /tmp/jscpd-baseline.txt

# Save baseline duplicate test names (per-file, same approach as main check)
while IFS= read -r -d '' f; do
  dupes=$(grep -oE "(it|test)\(['\"\`][^'\"\`]*['\"\`]" "$f" | sort | uniq -d)
  [ -n "$dupes" ] && echo "$f: $dupes"
done < <(find . -path ./node_modules -prune -o \( -name '*.spec.js' -o -name '*.test.js' \) -print0 2>/dev/null) > /tmp/test-names-baseline.txt

# Tag all branch tips (for range-diff after rebase)
for b in branch1 branch2 branch3; do
  git tag "pre-rebase/$b" "$b"
done

Without baselines, every finding during verification requires manual investigation to determine if it's pre-existing or rebase-introduced.

Agent Delegation Pattern

This pattern is optimized for Claude Code's Agent tool. On other agents, treat the agent list as a sequential checklist — order doesn't matter beyond Step 0 first, Step 5 last.

For large rebases, delegate verification to parallel agents:

Agent 1: git range-diff -s (commit correspondence)
Agent 2: sem entity-level diff — mcp__sem__sem_diff if available, else sem CLI
Agent 3: weave preview target (merge readiness, if available)
Agent 4: jscpd + grep (duplicate detection)
Agent 5: project validation suite (lint + types + tests)

Launch all 5 immediately after rebase (in parallel where supported, sequentially otherwise). Check range-diff and jscpd results first (arrive in seconds, highest signal). The gap between "rebase complete" and "verification results" is dangerous — kick off verification immediately, decide nothing until results arrive.

For a large change set, have Agent 2 follow its diff with mcp__sem__sem_impact on the modified entities and review the highest-fan-in one first — the entity with the most transitive dependents is where a botched conflict resolution does the most damage.

Classifying Findings

FindingClassificationAction
! commit in range-diffConflict resolutionReview the diff-of-diff
deleted entity in sem (backup-only, base=old/target=new)Potential lossCheck if intentionally deleted
Duplicate test block (same describe scope)Rebase artifactDelete the stale copy
Duplicate test name (cross describe scope)Pre-existing patternNote for future cleanup
weave conflictUnresolved divergenceExpected if target moved forward
lint/type errorRebase artifactFix immediately

Further Reading

See references/silent-behaviors.md for the silent exclusion thresholds that make test files invisible to sem/weave/jscpd.

What ships with it: 1 file

4.5 KB alongside SKILL.md

references/

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.