Skip to content
Development
Skill

/add-pattern

Add a new conflict-resolution pattern to GitWand core. Use this skill whenever someone wants to add a pattern, resolution rule, new conflict case, new heuristic, teach the resolver to handle a new kind of conflict automatically, or extend the pattern registry with a new

From plugin
gitwand
1725 skills3 agents2 commands
Install
$ npx -y skills add devlint/GitWand --skill add-pattern --agent claude-code

How it fires

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

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/add-pattern

Context preview

The summary Claude sees to decide when to auto-load this skill.

Add a new conflict-resolution pattern to GitWand core. Use this skill whenever someone wants to add a pattern, resolution rule, new conflict case, new heuristic, teach the resolver to handle a new kind of conflict automatically, or extend the pattern registry with a new

SKILL.md

add-pattern.SKILL.md
name: add-pattern
description: >
  Add a new conflict-resolution pattern to GitWand core. Use this skill
  whenever someone wants to add a pattern, resolution rule, new conflict case,
  new heuristic, teach the resolver to handle a new kind of conflict
  automatically, or extend the pattern registry with a new ConflictType.

Skill: add-pattern

Guide the agent through every step needed to add a new conflict-resolution pattern from end to end, touching all four required locations in the right order.

---

Step 1 — Gather information before writing any code

Ask the following questions up front. Do not start editing files until you have clear answers.

1. **Name** — What is the snake_case name for this pattern? (e.g. `comment_only_change`, `empty_block_insertion`)

2. **Trigger condition** — In plain English, when does this pattern apply? Be precise: what must be true of `oursLines`, `theirsLines`, and optionally `baseLines` for the pattern to fire?

3. **Resolution strategy** — What should the merged output look like when this pattern fires? (accept ours, accept theirs, union, base + additions, etc.)

4. **Confidence score** — What `typeClassification` value (0–100) do you propose, and why? What `dataRisk` value (0–100, where 0 = safe)? Use the existing patterns as a reference:

  • `same_change` / `one_side_change` / `delete_no_change` → typeClassification 100, dataRisk 0
  • `non_overlapping` → typeClassification 90, dataRisk 20
  • `whitespace_only` / `reorder_only` / `insertion_at_boundary` → typeClassification 85–90, dataRisk 8–20
  • `value_only_change` → typeClassification 72–88, dataRisk 25

5. **Priority** — What numeric priority should this pattern have? Lower = evaluated earlier. Current assignments:

  • 10 `same_change`, 20 `delete_no_change`, 30 `one_side_change`
  • 40 `non_overlapping`, 50 `whitespace_only`, 55 `reorder_only`
  • 57 `insertion_at_boundary`, 60 `value_only_change`, 999 `complex`

Pick a value that places it at the right point in the evaluation chain.

6. **`requires`** — Does the pattern need the base (diff3), work without it (diff2), or both? Use `"diff3"`, `"diff2"`, or `"both"`.

---

Step 2 — Add the ConflictType to `types.ts`

`packages/core/src/types.ts` contains the `ConflictType` union. Add the new type name there before creating the pattern file — TypeScript will then flag every location that needs updating.

// packages/core/src/types.ts
export type ConflictType =
  | "same_change"
  | "one_side_change"
  // ... existing types ...
  | "my_new_pattern"   // ← add here, with a short comment
  | "complex";

Also add a readable summary string for it in the `buildSummary()` switch inside `packages/core/src/classifier.ts`:

case "my_new_pattern":
  return "One-line human-readable description of the resolution.";

---

Step 3 — Create the pattern file

Create `packages/core/src/patterns/<name>.ts`.

The file must export a default `PatternPlugin` object — not a plain function. Copy the structure below and fill in every field.

/**
 * Pattern `my_new_pattern`
 *
 * <Two-sentence description of what this pattern detects and why it is safe
 * to auto-resolve.>
 *
 * Priority: <N> (<before/after which existing pattern>)
 * Requires: <diff3 | diff2 | both>
 */

import type { ClassifyInput, ConfidenceScore, PatternPlugin } from "../types.js";
import { scopeImpact, makeScore } from "./utils.js";

const myNewPattern: PatternPlugin = {
  type: "my_new_pattern",
  priority: <N>,
  requires: "<diff3|diff2|both>",

  detect(h: ClassifyInput): boolean {
    // Return true when this pattern applies.
    // Be conservative — false positives are worse than false negatives.
    return false; // replace with real logic
  },

  confidence(h: ClassifyInput): ConfidenceScore {
    const totalLines = Math.max(h.oursLines.length, h.theirsLines.length);
    return makeScore(
      <typeClassification>,  // 0–100, certainty of the classification
      <dataRisk>,            // 0–100, 0 = no data loss risk
      scopeImpact(totalLines),
      ["<booster: why we are confident>"],
      ["<penalty: why we are cautious, or empty array>"],
    );
  },

  explanation(h: ClassifyInput): string {
    return "Human-readable explanation shown in the UI (explain mode).";
  },

  passReason(h: ClassifyInput): string {
    return "Shown in DecisionTrace when this pattern matched.";
  },

  failReason(h: ClassifyInput): string {
    return "Shown in DecisionTrace when this pattern was tested but did not match.";
  },
};

export default myNewPattern;

Critical: context-line detection

If your `detect()` function ever inspects raw diff lines for context vs. added/removed:

// CORRECT — empty strings do NOT become phantom context lines
const isContext = (line: string) => line.startsWith(' ');

// WRONG — empty string passes this test and produces phantom context lines
const isContext = (line: string) => !line.startsWith('\\');

---

Step 4 — Register the pattern in `classifier.ts`

`packages/core/src/classifier.ts` owns the pattern registry. Add an import and add the plugin to the `PATTERNS` array in priority order.

// 1. Add the import near the other pattern imports
import myNewPattern from "./patterns/my-new-pattern.js";

// 2. Add to PATTERNS array — the array order is cosmetic (sort is by .priority),
//    but keep it in priority order for readability
const PATTERNS: PatternPlugin[] = [
  sameChange,           // priority 10
  // ...
  myNewPattern,         // priority <N>  ← add here
  // ...
  complex,              // priority 999 — MUST stay last
];

`complex` must always remain the last entry (priority 999, `detect()` always returns `true`) — it is the fallback for every unrecognized conflict.

---

Step 5 — Add a resolution case in `resolver/assemble.ts`

`packages/core/src/resolver/assemble.ts` contains the `assembleResolution()` function

Read more
Ships withgitwand

The Git client that actually resolves conflicts: 8 deterministic patterns auto-resolve the ones that were never decisions, full trace on the rest. Native (Tauri 2 + Rust), free, MIT.

Get the whole plugin
Stats
174
Stars
8
Forks
Active
Maintenance
TypeScript
Language
MIT
License
16h ago
Last commit
5mo ago
Created
14d ago
Added

Repo: devlint/GitWand

Other skills on gitwand.