# How the Reverse-Skill Routing Layer Scores and Prioritizes Rules

> Discover how the reverse-skill routing layer scores and prioritizes rules using regex matching, score accumulation, and priority-based selection for efficient skill assignment.

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

---

**The reverse-skill routing layer selects a PRIMARY skill by executing a three-step pipeline: regex-based keyword matching against route definitions, accumulation of match scores per route ID, and priority-ordered selection where the highest score wins and ties are broken by the configuration's `priority` array sequence.**

The routing layer in reverse-skill acts as the decision engine that maps user hints to specific reverse-engineering skills. Implemented in PowerShell and configured via JSON, the system processes input through `skills/scripts/master-route.ps1` to determine which route becomes active based on deterministic scoring logic defined in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json).

## Understanding the Routing Configuration Structure

The routing behavior is governed by two primary files: the JSON configuration that declares the rules and the PowerShell script that executes the matching algorithm.

### The routing.json Schema

[`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) serves as the single source of truth for all routing decisions. It defines route objects containing keyword patterns, a `priority` array that dictates tie-breaking order, and a `fallbackId` (defaulting to **R0**) for unmatched inputs. The configuration includes a self-check validation that ensures every route ID appears exactly once in the `priority` list, preventing configuration drift when new routes are added.

## Step-by-Step Rule Scoring Process

The routing algorithm executes three distinct phases to determine the PRIMARY route.

### Phase 1: Keyword Matching with Regex Filters

The router evaluates the incoming `$Hint` against each route's keyword objects defined in the JSON configuration. According to `master-route.ps1` (lines 41-50), a route enters the candidate list only when:

- The hint matches the `must` regular expression pattern.
- If `mustAll` is specified, **all** listed regexes must match simultaneously.
- The `exclude` pattern acts as a negative filter—if matched, it cancels the hit regardless of other matches.

Every successful hit adds that route's ID to a temporary candidate collection for further processing.

### Phase 2: Accumulating Match Scores

Once keyword matching completes, the router collapses the candidate list into a scoring dictionary (`$scores`) where keys represent route IDs and values count the number of keyword objects that fired. As implemented in `master-route.ps1` (lines 55-59), a route can accumulate multiple points if several of its keyword objects match the hint, allowing for granular weighting of complex routing rules.

### Phase 3: Priority-Based Selection and Tie-Breaking

The final selection iterates through the ordered `priority` array from top to bottom, comparing each route's accumulated score against the current maximum (`$maxScore`). Based on the logic in `master-route.ps1` (lines 74-87 and 91-97):

- The route with the **strictly highest** score becomes PRIMARY.
- When two routes share the same score, the one appearing **earlier** in the `priority` array wins because the script only updates the primary selection when encountering a strictly higher score.
- If no route accumulates any points, the system defaults to the `fallbackId` (**R0**).

## Practical Routing Examples

The following examples demonstrate the routing layer's behavior with real-world hints.

### Example 1: Single Match Selection

This example shows how the router handles a straightforward Android reverse-engineering request:

```powershell

# Assume we have a hint about Android reverse‑engineering

$hint = "I need to unpack an APK and bypass certificate pinning"
.\skills\scripts\master-route.ps1 -Hint $hint -OutDir "$HOME/reverse-skill-output"

```

The script matches the hint against **R1**'s `must` regex for APK reverse-engineering, increments its score to 1, and finds no higher-scoring competitors. Consequently, **R1** becomes the PRIMARY route and generates [`route-scope.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/route-scope.md) containing the primary ID, label, and path.

### Example 2: Tie-Breaking with Priority

This example illustrates the priority array's role in resolving equal scores:

```powershell

# Hint contains keywords that match both R5 (.NET reverse) and R6 (IDA reverse)

$hint = "I have a .NET binary that I want to decompile with IDA"
.\skills\scripts\master-route.ps1 -Hint $hint

```

Both **R5** and **R6** receive one point each. The router consults the `priority` array (ordered as R4, R1, R2, …, **R5**, **R6**, …, R0). Since **R5** appears before **R6**, the script selects **R5** as PRIMARY despite the equal scores, strictly following the configuration's tie-breaking hierarchy.

## Summary

- **Keyword filtering** uses `must`, `mustAll`, and `exclude` regex patterns in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) to determine initial route candidates.
- **Score accumulation** counts matching keyword objects per route ID in a PowerShell dictionary, allowing routes to earn multiple points.
- **Priority resolution** breaks ties by selecting the route appearing earliest in the `priority` array when scores are equal.
- **Fallback handling** routes unmatched hints to the configured `fallbackId` (**R0**) when no keywords match.
- **Configuration validation** ensures every route ID exists exactly once in the priority list, maintaining deterministic tie-breaking behavior.

## Frequently Asked Questions

### What happens if no routing rules match the input hint?

If the `$Hint` fails to trigger any keyword matches, the routing layer defaults to the `fallbackId` specified in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), which is typically set to **R0**. This guarantees that every user query receives a PRIMARY skill assignment even when specific keywords are absent.

### How does reverse-skill handle equal scores between multiple routes?

When two or more routes achieve identical scores, the system applies the `priority` array as a tie-breaker. The router iterates through the priority list sequentially and retains the first route it encounters with the current maximum score, ignoring subsequent routes with equal scores unless they exceed the current maximum.

### Where is the routing priority order defined and validated?

The priority sequence is defined in the `priority` array within [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json). The configuration includes a self-check mechanism that verifies every route ID appears exactly once in this array, issuing warnings if the priority list diverges from the defined routes to ensure consistent tie-breaking behavior.

### Can a route be excluded after matching the required keywords?

Yes. The `exclude` pattern in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) acts as a veto mechanism. If a hint matches the `must` or `mustAll` criteria but also matches the `exclude` regex, the hit is discarded and does not contribute to that route's score, preventing false positives from ambiguous terminology.