# How Scoring Logic Works for Task Routing in reverse-skill

> Understand reverse-skill task routing scoring logic. Learn how JSON-based scoring matrices combine base scores and keyword weights to select the best skill for user hints.

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

---

**The `reverse-skill` routing engine uses a JSON-based scoring matrix in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) that combines base scores with token-based keyword weights to deterministically select the best-matching skill for any user hint.**

Task routing in `reverse-skill` (github.com/zhaoxuya520/reverse-skill) is driven by a data-driven scoring system rather than hard-coded logic. The core routing matrix lives in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json), where each entry defines how hints map to executable skills. This design allows security researchers and automation engineers to extend routing behavior without modifying source code.

## The Routing JSON Structure

Each entry in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) contains four key fields that drive the scoring logic:

- **`hint`** — a string pattern (plain text or regex) matched against the user hint
- **`score`** — the base numeric weight for this entry
- **`keywords`** — an optional dictionary mapping tokens to additional weights
- **`script` / `command` / `tool`** — the executable skill to dispatch when this entry wins

The scoring logic treats regex patterns and literal strings uniformly, enabling flexible matching for complex patterns like `.*cve‑2021.*` alongside simple keyword triggers.

## How Match Scores Are Calculated

When a hint arrives (typically via [`skills/scripts/master-route.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/scripts/master-route.sh) or `skills/scripts/master-route.ps1`), the engine executes a five-step scoring pipeline:

1. **Normalize the hint** — convert to lowercase, trim whitespace, and tokenize into individual words
2. **Filter by pattern match** — skip entries whose `hint` pattern does not match the normalized hint
3. **Compute base score** — start with the entry's `score` value (defaults to `0`)
4. **Apply keyword boosts** — add weights for any tokens present in both the hint and the entry's `keywords` map:

   ```text
   matchScore = baseScore + Σ(keywords[token] for token in hint_tokens)
   ```

5. **Select winner** — choose the entry with highest `matchScore`; ties break by JSON file order (first-defined wins)

This deterministic tie-breaking ensures reproducible routing decisions even when multiple skills achieve identical scores.

## Code Example: The Scoring Algorithm

The actual implementation follows this Python pseudocode structure, matching the logic found in the routing scripts:

```python
import json
import re

def load_routing():
    with open('skills/config/routing.json') as f:
        return json.load(f)

def compute_score(entry, hint_tokens):
    """Calculate total score for a routing entry."""
    # Base priority from entry definition

    score = entry.get('score', 0)
    
    # Additive keyword weights for matched tokens

    keyword_weights = entry.get('keywords', {})
    for token in hint_tokens:
        score += keyword_weights.get(token, 0)
    
    return score

def route(hint):
    """Select best-matching skill for a user hint."""
    hint = hint.lower().strip()
    tokens = hint.split()
    
    best_entry = None
    best_score = -float('inf')
    
    for entry in load_routing():
        # Pattern match: regex or literal

        pattern = entry['hint']
        if not re.search(pattern, hint):
            continue
        
        candidate_score = compute_score(entry, tokens)
        
        # Strict greater-than enforces first-wins tie-breaking

        if candidate_score > best_score:
            best_score = candidate_score
            best_entry = entry
    
    return best_entry  # Contains skill to invoke

```

The production implementation in `skills/scripts/` adds error handling, logging, and cross-platform execution hooks for PowerShell, Bash, and Python skills.

## Key Design Characteristics

| Characteristic | Implementation Detail |
|----------------|----------------------|
| **Extensibility** | New skills append to [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json); no code changes required |
| **Granular control** | `keywords` map enables fine-tuning without inflating base `score` |
| **Regex flexibility** | Pattern matching supports complex security-relevant patterns (CVE IDs, hash types, etc.) |
| **Determinism** | Order-based tie-breaking guarantees consistent behavior across runs |

## Validation via Routing Benchmarks

The scoring logic is continuously validated against [`skills/tests/routing-benchmark.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/tests/routing-benchmark.json), which contains test cases pairing input hints with expected winning entries. This test suite ensures that:

- Score calculations remain stable as the routing matrix expands
- Keyword weight adjustments produce predictable ranking changes
- Regex patterns match intended hint variants

Run the benchmark to verify routing behavior after modifying any scores or keyword weights.

## Summary

- **[`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json)** stores the complete scoring matrix with base scores and optional keyword weight maps
- **Match scoring** combines entry `score` with token-based keyword boosts: `baseScore + sum(matching keyword weights)`
- **Tie-breaking** uses JSON file order (first entry wins), ensuring deterministic routing decisions
- **[`skills/tests/routing-benchmark.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/tests/routing-benchmark.json)** validates scoring outcomes against expected behavior
- **Zero-code extensibility**: add skills by appending entries; the `master-route` scripts automatically incorporate new scoring rules

## Frequently Asked Questions

### How do I add a new skill with custom scoring?

Append a new object to [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) with your `hint` pattern, base `score`, and optional `keywords` map. The `master-route` scripts will automatically consider it in the next routing decision—no code changes required.

### What happens when two entries have identical match scores?

The entry appearing earlier in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) wins. This first-defined-wins tie-breaking ensures reproducible routing even when scores collide.

### Can I use regular expressions in hint patterns?

Yes. The `hint` field accepts any valid Python `re.search()` pattern, enabling flexible matching for CVE identifiers, hash formats, IP addresses, and other security-relevant signatures.

### Where is the actual scoring code implemented?

The scoring logic resides in [`skills/scripts/master-route.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/scripts/master-route.sh) (Linux/macOS) and `skills/scripts/master-route.ps1` (Windows), with the configuration loaded from [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) as demonstrated in the code example above.