# What Is the Single Source of Truth for Routing Decisions in reverse-skill?

> Discover the single source of truth for routing decisions in reverse-skill. Learn how the routing.json configuration file guides your system's traffic flow efficiently.

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

---

**The single source of truth for routing decisions in reverse-skill is the JSON configuration file [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json).**

This file centrally defines every route, its matching keywords, priority ordering, and fallback behavior. All routing scripts in the repository—including `master-route.ps1`, `verify-routing-coherence.ps1`, and test utilities—read from this file at runtime. As implemented in zhaoxuya520/reverse-skill, no other file in the system determines routing logic; edits to routing must be made exclusively in this configuration.

## Where Routing Decisions Are Defined

The [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) file contains four top-level structures that collectively govern how user queries map to specific skills:

| Section | Purpose |
|---------|---------|
| `meta` | File metadata including description, version, fallback route ID (`R0`), scoring rules, and maintainer notes |
| `routes` | Mapping of route IDs (R1–R41, R0) to their labels, target skill files, and keyword matching rules |
| `priority` | Ordered array declaring tie-breaking precedence when multiple routes score equally |
| `keywords` (per-route) | Arrays of objects defining `must`, `exclude`, `mustAll`, and `note` fields for pattern matching |

You can view the complete source file at: [skills/config/routing.json](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json)

## How the JSON Structure Works

### Route Definition Example

Each entry in the `routes` object follows this pattern:

```json
"R12": {
  "label": "SQL Query Optimization",
  "skill": "database/sql-optimization/SKILL.md",
  "keywords": [
    {
      "must": "slow query|query performance|index tuning",
      "exclude": "hardware|server config",
      "note": "Matches database performance issues excluding infrastructure"
    }
  ]
}

```

The routing engine increments a score when the `must` pattern matches. If `exclude` is present and matches, that keyword rule is skipped. The `mustAll` field (where used) requires all listed terms to appear together.

### Priority Resolution

The `priority` array resolves scoring ties:

```json
"priority": ["R1", "R3", "R7", "R12", "R5", "R0"]

```

When multiple routes achieve identical scores, the system selects the route appearing earliest in this array. Routes not listed in `priority` receive implicit lowest precedence.

### Fallback Behavior

The `meta.fallbackId` field designates `R0` as the catch-all route:

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

```

## How Scripts Consume the Source of Truth

### Loading in PowerShell

The `master-route.ps1` script loads the routing table with:

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

# Access routes and priority

$routes = $routing.routes
$priorityOrder = $routing.priority
$fallbackRoute = $routes[$routing.meta.fallbackId]

```

### Loading in Python

For Python-based tooling or testing:

```python
import json
from pathlib import Path

def load_routing(repo_root: Path) -> dict:
    routing_path = repo_root / "skills" / "config" / "routing.json"
    with routing_path.open(encoding="utf-8") as f:
        return json.load(f)

def resolve_route(query: str, routing: dict) -> dict:
    scores = {}
    
    for route_id, route_data in routing["routes"].items():
        route_score = 0
        for kw in route_data.get("keywords", []):
            must_pattern = kw.get("must", "")
            exclude_pattern = kw.get("exclude")
            
            if must_pattern.lower() in query.lower():
                if exclude_pattern and exclude_pattern.lower() in query.lower():
                    continue
                route_score += 1
        
        if route_score > 0:
            scores[route_id] = route_score
    
    # Apply priority ordering

    for route_id in routing["priority"]:
        if route_id in scores:
            return routing["routes"][route_id]
    
    # Return fallback

    fallback_id = routing["meta"]["fallbackId"]
    return routing["routes"][fallback_id]

```

## Modifying Routing: The Correct Workflow

Because [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) is the **single source of truth**, follow this procedure when updating routing:

1. **Edit only [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json)** — Never modify generated files like [`MASTER-ROUTING.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/MASTER-ROUTING.md) or inline routing tables in skill documents.

2. **Add or update route entries** — Include unique route IDs, descriptive labels, correct skill file paths, and comprehensive keyword rules.

3. **Update the priority array** — Insert new route IDs at the appropriate position to establish precedence.

4. **Run verification** — Execute `verify-routing-coherence.ps1` to validate consistency between the JSON and derived artifacts:

```powershell
.\skills\scripts\verify-routing-coherence.ps1

```

This script cross-references the JSON against markdown route tables and reports discrepancies.

5. **Execute tests** — Confirm behavior with `test-routing.ps1`:

```powershell
.\skills\scripts\test-routing.ps1 -Verbose

```

## Key Files in the Routing System

| File | Path | Relationship to Source of Truth |
|------|------|--------------------------------|
| **Routing configuration (source of truth)** | [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) | Definitive routing definitions |
| Master routing script | `skills/scripts/master-route.ps1` | Reads JSON to dispatch queries |
| Coherence verifier | `skills/scripts/verify-routing-coherence.ps1` | Validates JSON-to-markdown consistency |
| Test suite | `skills/scripts/test-routing.ps1` | Automated validation of routing logic |
| Human-readable overview | [`skills/MASTER-ROUTING.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/MASTER-ROUTING.md) | Generated from JSON; do not edit directly |

## Summary

- **[`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json)** is the exclusive source of truth for routing decisions in reverse-skill
- All 42 routes (R1–R41 plus R0 fallback), their keywords, and priority ordering are defined in this single file
- PowerShell and Python scripts load this JSON at runtime; no hardcoded routing logic exists elsewhere
- Generated documentation and verification tools are downstream consumers—modifications belong only in the JSON
- The `priority` array and `meta.fallbackId` provide deterministic tie-breaking and default behavior

## Frequently Asked Questions

### Why is a JSON file used instead of inline code for routing?

JSON provides a language-agnostic, easily parseable format that both PowerShell and Python tooling can consume without modification. Separating configuration from implementation allows non-developers to adjust routing patterns without touching executable code, and enables automated validation through schema checking.

### What happens if two routes match with identical scores?

The `priority` array in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) determines selection order. The system iterates through `priority` and selects the first route ID that achieved the matching score. Routes absent from `priority` implicitly rank lowest. If no routes match, `meta.fallbackId` (R0) resolves automatically.

### Can I add keyword synonyms without creating a new route?

Yes—expand the `must` field within existing route keywords using pipe-delimited terms. For example, `"must": "deploy|release|ship|publish"` captures synonym variations under one route. For exclusions, add or extend the `exclude` field to filter false matches.

### How do I verify my routing.json changes are valid?

Run `verify-routing-coherence.ps1` to check that route IDs, labels, and skill paths align with markdown documentation. Then execute `test-routing.ps1` with sample queries to confirm expected route selection. Both scripts read exclusively from [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), ensuring your edits are the system of record.