How reverse-skill Prioritizes Routes in `routing.json`: Keyword Matching, Scoring, and Tie-Breaking Explained
reverse-skill uses a three-step deterministic process: keyword regex matching builds a candidate pool, the highest match count wins, and the "priority" array resolves ties, with "fallbackId" as a last resort.
The zhaoxuya520/reverse-skill repository implements a skill routing system that directs user prompts to specialized reverse-engineering modules. At its core, skills/config/routing.json defines how reverse-skill prioritizes routes through explicit scoring rules and an ordered precedence list. This article breaks down the exact algorithm using the source code implementation.
The Three-Step Routing Algorithm
The master routing scripts—master-route.ps1 (Windows) and master-route.sh (Linux/macOS)—execute the same logic defined in routing.json. The process follows three distinct phases.
Step 1: Keyword Matching Builds the Candidate Pool
Each route (R1, R2, … R41) contains a keywords array with regex-driven matching rules. The router evaluates every route against the input hint using three match types:
"must"— Required regex pattern; must match for the keyword to count"exclude"(optional) — If matched, disqualifies this keyword"mustAll"(optional) — Array of patterns; all must match for the keyword to count
In skills/config/routing.json, each matching keyword contributes +1 to that route's score. Routes with zero matches are excluded from the candidate pool.
{
"R1": {
"keywords": [
{
"must": "android|apk|dalvik|smali|certificate.?pinning",
"exclude": "ios|swift|frida-ios",
"mustAll": ["bypass", "pinning"]
}
],
"skill": "apk-reverse/SKILL.md"
}
}
Step 2: Highest Score Wins, Priority Array Breaks Ties
Once all routes are scored, the selection follows the meta rule documented at line 5-7 of routing.json:
"每条关键字规则命中后计入候选集;按
priority数组顺序取 ‘命中分数最高’ 的为 PRIMARY;分数并列时priority靠前者胜出;未命中任何规则时回退fallbackId."
Translation: After keyword evaluation, the route with the maximum match count becomes PRIMARY. When multiple routes share the highest score, the "priority" array determines the winner—the earlier the appearance, the higher the precedence.
The current priority ordering (lines 16-21) places R4 first and R0 last:
"priority": [
"R4","R1","R2","R3","R30","R31","R33","R5","R9","R21",
"R22","R6","R7","R8","R34","R28","R17","R16","R18","R24",
"R37","R23","R35","R25","R36","R29","R38","R32","R26","R27",
"R10","R11","R12","R13","R14","R15","R19","R40","R20","R39",
"R41","R0"
]
This explicit ordering allows fine-grained control over route precedence independent of score distribution.
Step 3: Fallback Routing
If no keywords match across all routes, the router selects the route specified by "fallbackId" (line 4-6). By default, this is "R0"—a generic reverse-engineering skill ensuring the system always produces a response.
"meta": {
"fallbackId": "R0",
"description": "Default routing when no keywords match"
}
Practical Example: Routing a Certificate Pinning Query
Consider an input hint: "How do I bypass Android certificate pinning?"
The execution flow in master-route.sh proceeds as follows:
# Invoke the router with a hint
bash skills/scripts/master-route.sh --hint "How do I bypass Android certificate pinning?"
Internal logic (conceptual):
import json, re, sys
routing = json.load(open('skills/config/routing.json'))
hint = sys.argv[1].lower()
scores = {}
for rid, rdata in routing['routes'].items():
match_cnt = 0
for kw in rdata['keywords']:
if re.search(kw['must'], hint):
# Check exclusion patterns
if 'exclude' in kw and re.search(kw['exclude'], hint):
continue
# Check mustAll conjunction
if 'mustAll' in kw and not all(re.search(p, hint) for p in kw['mustAll']):
continue
match_cnt += 1
if match_cnt:
scores[rid] = match_cnt
# Selection phase
if not scores:
selected = routing['meta']['fallbackId'] # "R0"
else:
max_score = max(scores.values())
candidates = [r for r, s in scores.items() if s == max_score]
# Tie-breaker: walk priority array in order
for rid in routing['priority']:
if rid in candidates:
selected = rid
break
print(f"Selected: {selected} → {routing['routes'][selected]['skill']}")
For this hint, R1 wins because:
"certificate.?pinning"matches (score 1)- No other route achieves a higher match count
R1appears second in thepriorityarray, securing victory if tied
Key Source Files and Their Roles
| File | Purpose |
|---|---|
skills/config/routing.json |
Central configuration—routes, keywords, priority array, fallbackId |
skills/scripts/master-route.sh / master-route.ps1 |
Cross-platform entry points implementing the three-step algorithm |
skills/scripts/verify-routing-coherence.ps1 |
Validates that priority ordering matches MASTER-ROUTING.md documentation |
skills/scripts/test-routing.sh / test-routing.ps1 |
Automated test suite exercising all route combinations |
The verify-routing-coherence.ps1 script ensures the priority array remains synchronized with human-readable documentation—a critical check given that the array order directly affects runtime behavior.
Summary
- Keyword regex matching filters routes into a scored candidate pool using
must,exclude, andmustAllpatterns - Highest score selection promotes the most specific match; multiple hits accumulate
"priority"array tie-breaking provides deterministic precedence when scores equal"fallbackId"guarantees a default route (R0) when no keywords match- The algorithm is implemented identically in
master-route.ps1andmaster-route.sh, with validation viaverify-routing-coherence.ps1
Frequently Asked Questions
What happens if two routes have the same keyword match count?
The router consults the "priority" array in skills/config/routing.json. The route appearing earlier in this ordered list wins. For example, if both R4 and R1 score 2 matches, R4 wins because it occupies index 0 versus R1 at index 1.
Can I change route priority without modifying keyword patterns?
Yes. The "priority" array is designed for this exact use case. Rearranging route IDs in this list changes tie-breaking behavior without touching individual keyword definitions. Run verify-routing-coherence.ps1 after edits to ensure documentation consistency.
What is R0 and why is it always last in priority?
R0 is the fallback route—a generic reverse-engineering skill triggered when no keywords match. It appears last in the "priority" array so it never wins a tie against specific matches, yet remains available via fallbackId for unmatched inputs.
How do I test routing behavior for a new skill?
Use skills/scripts/test-routing.sh (or .ps1 on Windows). This suite validates scoring and priority resolution across all routes. Add your hint to the test matrix to verify correct dispatch before deployment.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →