# How Priority and Tie-Breaking Work When Multiple Routing Rules Match in reverse-skill

> Learn how reverse-skill handles multiple routing rule matches. Discover how scores, keywords, and priority arrays ensure accurate routing.

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

---

**When multiple routing rules match in reverse-skill, the engine accumulates scores for each route based on keyword hits, selects the highest-scoring candidate, and breaks ties using the ordered priority array defined in routing.json.**

The reverse-skill repository implements a deterministic routing system that resolves ambiguous keyword matches through a structured scoring mechanism. Understanding how priority and tie-breaking work when multiple routing rules match is essential for customizing the routing behavior and ensuring predictable route selection.

## Routing Configuration and Score Accumulation

### The Single Source of Truth in routing.json

All routing logic stems from [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), which serves as the authoritative configuration for the entire engine. This file defines the `meta.scoring` rules and the ordered `priority` array that governs tie resolution. Each route identifier (R1, R2, etc.) maps to a set of keyword patterns, and the **meta.scoring** field (lines 5‑7) establishes that every matched keyword contributes one point to that route's total score.

### Score Accumulation Mechanics

When processing a user hint, the engine iterates through all defined routes and tests the input against each keyword's `must` pattern. Every successful match increments the route's score by exactly one point. The system aggregates these hits across all patterns to produce a final score for each candidate route, creating a ranked list of potential matches.

## Priority-Based Tie-Breaking Logic

### Resolving Equal Scores with the Priority Array

If two or more routes share the identical highest score, the system consults the **`priority`** array defined near the end of [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) (lines 24‑29). The route appearing **earlier** in this ordered list wins the tie, ensuring deterministic selection regardless of match order. For example, given the hint "apk reverse and ida analysis", both R1 (APK) and R6 (IDA) receive one hit; if the `priority` array lists them as `R4, R1, …, R6`, R1 is selected as the primary route because it appears first.

### Fallback Mechanism

When no route receives any score—meaning no keywords matched the input—the engine defaults to the route specified in `meta.fallbackId`. By convention, this fallback is set to R0, ensuring the routing pipeline always returns a valid route identifier even in the absence of matches.

## Implementation in master-route.ps1

The PowerShell script `skills/scripts/master-route.ps1` implements this logic at runtime by loading the JSON configuration and applying the scoring and tie-breaking algorithms:

```powershell

# Load routing.json

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

# Build candidate scores

$candidates = @{}
foreach ($id in $routing.routes.Keys) {
    $score = 0
    foreach ($kw in $routing.routes[$id].keywords) {
        if ($hint -match $kw.must) { $score++ }
    }
    if ($score -gt 0) { $candidates[$id] = $score }
}

# Determine primary route

if ($candidates.Count -eq 0) {
    $primary = $routing.meta.fallbackId   # R0

} else {
    $maxScore = $candidates.Values | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum
    $top = $candidates.GetEnumerator() | Where-Object {$_.Value -eq $maxScore}
    # Tie-break with priority order

    $primary = $routing.priority | Where-Object { $top.Name -contains $_ } | Select-Object -First 1
}

```

This implementation strictly follows the four-step resolution process: accumulate scores, select the maximum, break ties via the priority array, and fall back to R0 when necessary.

## Verification and Coherence Enforcement

To prevent configuration drift that could alter tie-breaking behavior, the repository includes `skills/scripts/verify-routing-coherence.ps1`. This verification script ensures the `priority` array maintains a 1-to-1 mapping with the routing table documented in [`skills/MASTER-ROUTING.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/MASTER-ROUTING.md), enforcing consistency between the JSON configuration and human-readable documentation. Additionally, [`skills/tests/routing-benchmark.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/tests/routing-benchmark.json) provides validation data to confirm that routing decisions behave as expected across different input scenarios.

## Summary

- The routing engine uses [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) as the single source of truth for all matching and scoring logic.
- Each matched keyword adds one point to its route's score, with the highest aggregate score determining the primary candidate.
- When multiple routes share the top score, the route appearing earliest in the `priority` array wins the tie, providing deterministic resolution.
- The `meta.fallbackId` (default R0) serves as the default route when no keywords produce a match.
- The `verify-routing-coherence.ps1` script validates that the priority configuration aligns with [`MASTER-ROUTING.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/MASTER-ROUTING.md).

## Frequently Asked Questions

### How does reverse-skill handle multiple routes with identical scores?

When two or more routes achieve the same highest score, the engine references the ordered `priority` array in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json). The route positioned earliest in this array receives preference, ensuring deterministic selection even when multiple patterns match the input hint simultaneously.

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

If no keywords match and the candidate dictionary remains empty, the system immediately falls back to the route specified in `meta.fallbackId`. By default, this value is set to R0, guaranteeing that the routing pipeline always returns a valid route identifier rather than failing.

### Where is the priority order defined in the codebase?

The priority order is defined in the `priority` field within [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), typically located near the end of the file (lines 24‑29). This array is strictly enforced by `verify-routing-coherence.ps1` to maintain synchronization with the table in [`skills/MASTER-ROUTING.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/MASTER-ROUTING.md).

### Can the scoring logic be customized without modifying source code?

Yes. Since `master-route.ps1` derives all logic from [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), you can modify keyword patterns, adjust the `priority` array order, or change the `fallbackId` to alter tie-breaking behavior without editing the PowerShell implementation itself.