# How the Routing Rule Priority System Works in reverse‑skill

> Understand reverse-skill routing rule priority. Learn how the system selects execution paths and uses fallback IDs when multiple rules match user requests. Optimize your routing logic.

- Repository: [ZhaoXu/reverse-skill](https://github.com/zhaoxuya520/reverse-skill)
- Tags: internals
- Published: 2026-09-02

---

**The reverse‑skill router uses a deterministic priority array defined in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) to select the primary execution path when multiple routing rules match a user request, falling back to `meta.fallbackId` (typically `R0`) when no keywords match.**

The **reverse‑skill** repository implements a request routing mechanism that directs user inputs to specialized reverse‑engineering skills based on keyword patterns. At the heart of this system lies a single source of truth in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), where the `priority` array (lines 322‑329) establishes a global hierarchy for all route IDs. This declarative approach ensures that when user hints satisfy multiple skill patterns, the engine consistently selects the most appropriate module based on a curated specificity order rather than arbitrary selection.

## The Four‑Step Routing Decision Process

When processing a user request, the routing engine executes a precise sequence to determine the **PRIMARY** skill. This workflow guarantees deterministic behavior across all entry points in the codebase.

### 1. Keyword Matching and Candidate Selection

The router first evaluates every rule defined in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) against the user input. Each rule contains `must` regex patterns and optional `exclude` patterns that define activation conditions. Rules satisfying these constraints enter a candidate set for secondary evaluation.

### 2. Scoring Based on Keyword Satisfaction

Each candidate receives a score calculated from the number of keyword groups that triggered a match. Higher scores indicate stronger relevance between the user input and the skill's defined triggers. This quantitative measure distinguishes between partial and comprehensive matches.

### 3. Priority Array Resolution

The critical decision point occurs in the `priority` array at the bottom of [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json). The engine sorts candidates by their position in this ordered list, with smaller indices indicating higher precedence. When scores are equal, the rule appearing **earliest** in the `priority` array wins the PRIMARY designation.

### 4. Fallback to Default Route

If no keywords match any rule, the system invokes the fallback mechanism defined in `meta.fallbackId`. By convention, this routes to `R0` (General reverse‑engineering), ensuring the system always provides a response even for ambiguous or non‑specific inputs.

## The Priority Array Structure

Located at lines 322‑329 of [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), the `priority` array encodes a **global ordering** from most specific to most general skills. For example, DSL‑VM reverse (`R4`) appears before APK reverse (`R1`), reflecting architectural decisions about skill specificity and importance.

```json
{
  "priority": ["R4", "R1", "R5", "R9", "R2", "R3", "R6", "R7", "R8"],
  "meta": {
    "fallbackId": "R0"
  }
}

```

This structure means modifying routing behavior requires only adjusting the JSON file. The core router logic in `master-route.ps1` and validation scripts remain unchanged when adding or reordering routes.

## Implementation Across the Codebase

### JavaScript Priority Resolution Logic

The following pattern from the codebase demonstrates how to programmatically select the primary route using the priority array index:

```javascript
const routing = require('./skills/config/routing.json');

function choosePrimary(matchedIds) {
  // Filter to valid candidates only
  const candidates = matchedIds.filter(id => routing.routes[id]);
  
  // Sort by priority array index (smaller index = higher priority)
  candidates.sort((a, b) => {
    const pa = routing.priority.indexOf(a);
    const pb = routing.priority.indexOf(b);
    return pa - pb;
  });
  
  // Return highest priority match or fallback
  return candidates[0] || routing.meta.fallbackId;
}

// Example: R5 appears before R9 in priority array
console.log(choosePrimary(['R5', 'R9'])); // → "R5"

```

### PowerShell Router Implementation

The `master-route.ps1` script implements the priority lookup using pipeline filtering against the ordered array:

```powershell
$routing = Get-Content -Raw "$PSScriptRoot/../skills/config/routing.json" | ConvertFrom-Json

# Collect all matching route IDs

$matched = @()
foreach ($id in $routing.routes.Keys) {
    foreach ($kw in $routing.routes[$id].keywords) {
        if ($Hint -match $kw.must -and (-not $kw.exclude -or $Hint -notmatch $kw.exclude)) {
            $matched += $id
            break
        }
    }
}

# Resolve using priority array order (first match wins)

$primary = $routing.priority | Where-Object { $matched -contains $_ } | Select-Object -First 1
if (-not $primary) { $primary = $routing.meta.fallbackId }

Write-Host "Routing to $primary → $($routing.routes[$primary].skill)"

```

### Validation and Consistency Checks

The `verify-routing-coherence.ps1` script ensures the priority list remains synchronized with route definitions to prevent orphaned IDs:

```bash
node -e "
const routing = require('./skills/config/routing.json');
const docIds = Object.keys(routing.routes);
const missing = routing.priority.filter(p => !docIds.includes(p));
if (missing.length) console.error('Priority contains unknown IDs:', missing);
else console.log('Priority list matches route definitions.');
"

```

## Benefits of the Priority‑Based Architecture

**Deterministic Routing**: Because the `priority` array provides a fixed linear order, identical inputs always resolve to identical primary skills. This eliminates non‑deterministic behavior that could occur with hash‑based or unordered selections.

**System Extensibility**: Adding new routing rules requires only appending to `routes` and inserting the ID into the `priority` array at the appropriate specificity level. Neither `master-route.ps1` nor the verification scripts in `skills/scripts/` require modification to accommodate new entries.

**Cross‑Script Consistency**: All routing entry points—including `master-route.ps1`, `verify-routing-coherence.ps1`, [`test-routing.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/test-routing.sh), and `test-routing.ps1`—read from the same [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) file. This guarantees that command‑line tools, validation suites, and automated tests operate with identical logic and priorities.

## Summary

- The routing priority system in reverse‑skill relies on a linear `priority` array in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) (lines 322‑329) to establish a global ordering of route IDs from most to least specific.
- When multiple rules match, the engine selects the candidate with the highest keyword score that appears earliest in the priority list.
- The fallback mechanism defaults to `meta.fallbackId` (conventionally `R0`) when no keywords match, ensuring system resilience.
- All scripts consume the same JSON configuration, maintaining consistency across the routing pipeline.
- This declarative approach separates routing policy from implementation logic, enabling safe modifications without code changes.

## Frequently Asked Questions

### How does reverse‑skill handle ties when two rules have the same match score?

When two rules achieve identical scores during keyword evaluation, the system breaks ties using the `priority` array order. The rule with the smaller index (appearing earlier) in the `priority` list becomes the PRIMARY route. This convention is implemented consistently across both the JavaScript and PowerShell routing implementations in the repository.

### Can I modify the priority order without changing the core router code?

Yes. The `priority` array in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) is the sole authority for route precedence. Adjusting the array order immediately affects routing behavior without requiring modifications to `master-route.ps1` or other scripts. However, you should run `verify-routing-coherence.ps1` after changes to ensure all IDs in the priority list correspond to valid route definitions in the `routes` object.

### What happens if a route ID exists in the priority array but not in the routes object?

The validation scripts explicitly check for this condition. If `verify-routing-coherence.ps1` detects an ID in `priority` that lacks a corresponding entry in `routes`, it reports an error. During actual routing, such orphaned IDs are simply ignored during the candidate matching phase, though this configuration represents an error state that should be corrected immediately.

### Where is the fallback route defined if no keywords match?

The fallback destination is defined in the `meta.fallbackId` field within [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), typically set to `"R0"` for General reverse‑engineering. This value is referenced by both the JavaScript `choosePrimary` function (returning `routing.meta.fallbackId` when the candidates array is empty) and the PowerShell router (assigning `$routing.meta.fallbackId` to `$primary` when no priority matches exist).