# How the Routing Priority Array in routing.json Determines Skill Selection in reverse-skill

> Understand how the routing priority array in routing.json in reverse-skill selects the correct skill when multiple keywords match. Learn the tie-breaking logic for deterministic skill selection.

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

---

**The `priority` array in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) serves as a deterministic tie-breaker: after scoring all keyword matches, the router selects the first route from the `priority` list that appears among the highest-scoring candidates.**

The `reverse-skill` repository implements a two-stage routing system where multiple skills can match the same user prompt. When keyword overlaps occur, the `priority` array guarantees consistent and predictable skill selection without arbitrary randomness. This mechanism is central to how the platform routes requests to the appropriate skill handler.

## The Two-Stage Routing Pipeline

The routing logic operates in distinct phases, each defined in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json). Understanding both stages clarifies why the `priority` array matters.

### Stage 1: Keyword Matching and Scoring

Every incoming request is evaluated against all routes defined in the `routes` section of [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json). Each route contains a `keywords` list with `must` patterns and optional `exclude` patterns.

The scoring rules are documented in the **meta** section (lines 5–7):

```json
{
  "meta": {
    "scoringRule": "count_of_satisfied_keyword_rules",
    "fallbackId": "R0",
    "description": "Route priority: lower index = higher priority"
  }
}

```

For each route, the router increments the score by 1 for every keyword rule whose `must` pattern matches and whose `exclude` pattern (if present) does not match. Routes with zero matches are discarded.

### Stage 2: Priority Resolution for Ties

When multiple routes achieve the same highest score, the `priority` array (lines 16–21) breaks the tie:

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

```

The router traverses this array left-to-right and selects the **first route ID** that exists in the candidate set. Leftmost position indicates highest precedence.

## Implementation Details from the Source Code

### Core Selection Logic

The routing scripts implement this pipeline in Python. The scoring and priority resolution work as follows:

```python
import json
import re

def select_skill(prompt):
    with open('skills/config/routing.json') as f:
        routing = json.load(f)

    candidates = {}
    
    # Stage 1: Keyword matching → compute scores

    for rid, route in routing['routes'].items():
        score = 0
        for kw in route['keywords']:
            if re.search(kw['must'], prompt):
                if 'exclude' not in kw or not re.search(kw['exclude'], prompt):
                    score += 1
        if score:
            candidates[rid] = score

    if not candidates:
        return routing['meta']['fallbackId']  # → "R0"

    # Identify highest-scoring candidates

    max_score = max(candidates.values())
    highest = [rid for rid, s in candidates.items() if s == max_score]

    # Stage 2: Apply priority ordering

    for rid in routing['priority']:
        if rid in highest:
            return rid  # selected route ID

    return routing['meta']['fallbackId']  # defensive fallback

```

### Entry Point Scripts

The platform invokes routing through wrapper scripts. In `skills/scripts/master-route.ps1` (Windows) or [`master-route.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/master-route.sh) (Linux/macOS):

```powershell
$hint = "<user prompt>"
$selectedId = & python -c "import select; print(select.select_skill('$hint'))"

Write-Host "Routing selected: $selectedId"

# Subsequent logic loads the corresponding SKILL.md using the route's 'skill' field

```

The `select_skill()` function encapsulates the **score → priority → fallback** pipeline that determines which skill content gets retrieved.

## Routing Priority Array: Design Intent

The `priority` array in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) serves three critical purposes:

- **Determinism** — Same input always produces same output, regardless of JSON key ordering or hash randomization
- **Explicit precedence** — Route priority is human-readable and version-controlled
- **Conflict resolution** — Overlapping keyword patterns are resolved through intentional ordering rather than implementation-dependent behavior

A validation script `skills/scripts/verify-routing-coherence.ps1` ensures the `priority` array remains synchronized with [`skills/MASTER-ROUTING.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/MASTER-ROUTING.md), preventing documentation drift.

## Example Scenario: Multiple Keyword Matches

Consider two routes:

| Route ID | Keywords Matched | Score |
|----------|------------------|-------|
| R3 | "api", "design" | 2 |
| R5 | "api", "design" | 2 |

Both routes match equally. With `priority: ["R1", "R3", "R2", "R5", ...]`, the router selects **R3** because it appears before R5 in the array.

If the `priority` array were `["R1", "R5", "R3", "R2", ...]`, the selection would be **R5** instead.

## Summary

- The `priority` array in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) provides deterministic tie-breaking when multiple routes achieve identical keyword match scores
- Route selection follows a strict **score → priority → fallback** pipeline implemented in `skills/scripts/master-route.ps1` and [`master-route.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/master-route.sh)
- Array position determines precedence: leftmost routes win ties against rightmost routes
- The `fallbackId` ("R0") catches cases where no keywords match or unexpected errors occur
- Coherence between `priority` array and documentation is enforced by `verify-routing-coherence.ps1`

## Frequently Asked Questions

### What happens if no routes match any keywords?

The router returns the `fallbackId` defined in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json)'s meta section, which defaults to `"R0"`. This route typically contains a generic skill handler or error response.

### Can the `priority` array contain routes that don't exist in the `routes` section?

While technically possible in JSON, the `verify-routing-coherence.ps1` script validates consistency between all routing definitions. Missing routes in the `priority` array would cause validation failures in the CI pipeline.

### How does scoring handle partial keyword matches?

Each satisfied keyword rule contributes exactly 1 point to a route's score. The router uses simple counting rather than weighted scoring, making the priority array's role as tie-breaker more significant for complex routing scenarios.

### Where should I modify routing behavior for a new skill?

Add your route to [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) in the `routes` section, then insert your route ID into the `priority` array at your desired precedence position. Update [`skills/MASTER-ROUTING.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/MASTER-ROUTING.md) to document the change, and run `verify-routing-coherence.ps1` before committing.