# How reverse-skill Prioritizes Routes in `routing.json`: Keyword Matching, Scoring, and Tie-Breaking Explained

> Learn how reverse-skill prioritizes routes in routing.json using keyword matching, scoring, and tie-breaking. Understand the deterministic process for optimal routing.

- Repository: [ZhaoXu/reverse-skill](https://github.com/zhaoxuya520/reverse-skill)
- Tags: deep-dive
- Published: 2026-08-20

---

**reverse-skill uses a three-step deterministic process: keyword regex matching builds a candidate pool, the highest match count wins, and the `"priority"` array resolves ties, with `"fallbackId"` as a last resort.**

The `zhaoxuya520/reverse-skill` repository implements a skill routing system that directs user prompts to specialized reverse-engineering modules. At its core, [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) defines how reverse-skill prioritizes routes through explicit scoring rules and an ordered precedence list. This article breaks down the exact algorithm using the source code implementation.

---

## The Three-Step Routing Algorithm

The master routing scripts—`master-route.ps1` (Windows) and [`master-route.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/master-route.sh) (Linux/macOS)—execute the same logic defined in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json). The process follows three distinct phases.

### Step 1: Keyword Matching Builds the Candidate Pool

Each route (`R1`, `R2`, … `R41`) contains a `keywords` array with regex-driven matching rules. The router evaluates every route against the input hint using three match types:

- **`"must"`** — Required regex pattern; must match for the keyword to count
- **`"exclude"`** (optional) — If matched, disqualifies this keyword
- **`"mustAll"`** (optional) — Array of patterns; all must match for the keyword to count

In [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), each matching keyword contributes **+1** to that route's score. Routes with zero matches are excluded from the candidate pool.

```json
{
  "R1": {
    "keywords": [
      {
        "must": "android|apk|dalvik|smali|certificate.?pinning",
        "exclude": "ios|swift|frida-ios",
        "mustAll": ["bypass", "pinning"]
      }
    ],
    "skill": "apk-reverse/SKILL.md"
  }
}

```

### Step 2: Highest Score Wins, Priority Array Breaks Ties

Once all routes are scored, the selection follows the meta rule documented at line 5-7 of [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json):

> "每条关键字规则命中后计入候选集；**按 `priority` 数组顺序取 ‘命中分数最高’ 的为 PRIMARY**；分数并列时 `priority` 靠前者胜出；未命中任何规则时回退 `fallbackId`."

Translation: After keyword evaluation, the route with the maximum match count becomes **PRIMARY**. When multiple routes share the highest score, the `"priority"` array determines the winner—the earlier the appearance, the higher the precedence.

The current priority ordering (lines 16-21) places `R4` first and `R0` last:

```json
"priority": [
  "R4","R1","R2","R3","R30","R31","R33","R5","R9","R21",
  "R22","R6","R7","R8","R34","R28","R17","R16","R18","R24",
  "R37","R23","R35","R25","R36","R29","R38","R32","R26","R27",
  "R10","R11","R12","R13","R14","R15","R19","R40","R20","R39",
  "R41","R0"
]

```

This explicit ordering allows fine-grained control over route precedence independent of score distribution.

### Step 3: Fallback Routing

If **no** keywords match across all routes, the router selects the route specified by `"fallbackId"` (line 4-6). By default, this is `"R0"`—a generic reverse-engineering skill ensuring the system always produces a response.

```json
"meta": {
  "fallbackId": "R0",
  "description": "Default routing when no keywords match"
}

```

---

## Practical Example: Routing a Certificate Pinning Query

Consider an input hint: *"How do I bypass Android certificate pinning?"*

The execution flow in [`master-route.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/master-route.sh) proceeds as follows:

```bash

# Invoke the router with a hint

bash skills/scripts/master-route.sh --hint "How do I bypass Android certificate pinning?"

```

Internal logic (conceptual):

```python
import json, re, sys

routing = json.load(open('skills/config/routing.json'))
hint = sys.argv[1].lower()

scores = {}
for rid, rdata in routing['routes'].items():
    match_cnt = 0
    for kw in rdata['keywords']:
        if re.search(kw['must'], hint):
            # Check exclusion patterns

            if 'exclude' in kw and re.search(kw['exclude'], hint):
                continue
            # Check mustAll conjunction

            if 'mustAll' in kw and not all(re.search(p, hint) for p in kw['mustAll']):
                continue
            match_cnt += 1
    if match_cnt:
        scores[rid] = match_cnt

# Selection phase

if not scores:
    selected = routing['meta']['fallbackId']  # "R0"

else:
    max_score = max(scores.values())
    candidates = [r for r, s in scores.items() if s == max_score]
    # Tie-breaker: walk priority array in order

    for rid in routing['priority']:
        if rid in candidates:
            selected = rid
            break

print(f"Selected: {selected} → {routing['routes'][selected]['skill']}")

```

For this hint, `R1` wins because:
- `"certificate.?pinning"` matches (score 1)
- No other route achieves a higher match count
- `R1` appears second in the `priority` array, securing victory if tied

---

## Key Source Files and Their Roles

| File | Purpose |
|------|---------|
| [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) | Central configuration—routes, keywords, `priority` array, `fallbackId` |
| [`skills/scripts/master-route.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/scripts/master-route.sh) / `master-route.ps1` | Cross-platform entry points implementing the three-step algorithm |
| `skills/scripts/verify-routing-coherence.ps1` | Validates that `priority` ordering matches [`MASTER-ROUTING.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/MASTER-ROUTING.md) documentation |
| [`skills/scripts/test-routing.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/scripts/test-routing.sh) / `test-routing.ps1` | Automated test suite exercising all route combinations |

The `verify-routing-coherence.ps1` script ensures the `priority` array remains synchronized with human-readable documentation—a critical check given that the array order directly affects runtime behavior.

---

## Summary

- **Keyword regex matching** filters routes into a scored candidate pool using `must`, `exclude`, and `mustAll` patterns
- **Highest score selection** promotes the most specific match; multiple hits accumulate
- **`"priority"` array tie-breaking** provides deterministic precedence when scores equal
- **`"fallbackId"`** guarantees a default route (`R0`) when no keywords match
- The algorithm is implemented identically in `master-route.ps1` and [`master-route.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/master-route.sh), with validation via `verify-routing-coherence.ps1`

---

## Frequently Asked Questions

### What happens if two routes have the same keyword match count?

The router consults the `"priority"` array in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json). The route appearing earlier in this ordered list wins. For example, if both `R4` and `R1` score 2 matches, `R4` wins because it occupies index 0 versus `R1` at index 1.

### Can I change route priority without modifying keyword patterns?

Yes. The `"priority"` array is designed for this exact use case. Rearranging route IDs in this list changes tie-breaking behavior without touching individual keyword definitions. Run `verify-routing-coherence.ps1` after edits to ensure documentation consistency.

### What is `R0` and why is it always last in priority?

`R0` is the **fallback route**—a generic reverse-engineering skill triggered when no keywords match. It appears last in the `"priority"` array so it never wins a tie against specific matches, yet remains available via `fallbackId` for unmatched inputs.

### How do I test routing behavior for a new skill?

Use [`skills/scripts/test-routing.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/scripts/test-routing.sh) (or `.ps1` on Windows). This suite validates scoring and priority resolution across all routes. Add your hint to the test matrix to verify correct dispatch before deployment.