How Routing Rule Scores Are Calculated and Prioritized When There Are Ties in Reverse-Skill
Routing rule scores in reverse-skill are calculated as (match count × weight) + basePriority, with ties broken first by rule order in routing.json (earlier rules win) and second by alphabetical rule ID.
The reverse-skill routing system determines which skill to execute by assigning a numeric score to each candidate rule based on keyword matches. This article explains the exact scoring algorithm implemented in the PowerShell verification scripts, how the configuration file defines weights and priorities, and the deterministic tie-breaking strategy that ensures consistent rule selection.
Understanding the Routing Score Calculation
The scoring engine tokenizes user hints and compares them against rule definitions in skills/config/routing.json. Each potential match contributes to a final score that determines routing priority.
Keyword Matching and Tokenization
When a user provides a hint (for example, "enumerate system processes"), the system splits the input into lowercase tokens. Each rule's keywords array is checked against these tokens to determine matches.
Weight Application and Base Priority
Individual keywords can carry different weights. If a rule defines a weight field for a specific keyword, that value replaces the default multiplier of 1. Additionally, rules may declare a basePriority value (defaulting to 0) to boost their standing regardless of keyword matches.
The Scoring Formula
The total score follows this arithmetic as implemented in skills/scripts/verify-routing-coherence.ps1:
totalScore = Σ(matchedKeywordWeight) + basePriority
For each keyword match, the system adds the configured weight (or 1 if unspecified) to the running total, then adds the rule's basePriority to produce the final value.
Tie-Breaking Mechanism When Scores Are Equal
When multiple rules achieve identical totalScore values, the system applies a two-tier deterministic resolution strategy to prevent ambiguous routing.
Primary Tie-Breaker: Rule Order in routing.json
The router selects the rule that appears earlier in the routing.json configuration file. Array index position serves as the first differentiator, giving repository maintainers explicit control over precedence without adjusting numeric scores.
Secondary Tie-Breaker: Lexicographic Rule ID
If rules share the same score and index position (possible with programmatically generated configurations), the system falls back to lexicographic ordering of the rule's id field. The rule with the alphabetically first identifier receives priority.
Implementation in verify-routing-coherence.ps1
The skills/scripts/verify-routing-coherence.ps1 script implements this logic iteratively. It tracks the best-matching rule by comparing scores and applying tie-breakers during the enumeration:
$hint = "enumerate system processes"
$tokens = $hint -split '\s+' | ForEach-Object { $_.ToLower() }
$bestRule = $null
$bestScore = -1
$bestRuleIndex = -1
$index = 0
foreach ($rule in $routingConfig.rules) {
$score = $rule.basePriority
foreach ($kw in $rule.keywords) {
if ($tokens -contains $kw) {
$weight = $rule.weights[$kw] ?? 1
$score += $weight
}
}
# Tie-breaker: earlier rule wins on equal score
if ($score -gt $bestScore -or
($score -eq $bestScore -and $index -lt $bestRuleIndex)) {
$bestRule = $rule
$bestScore = $score
$bestRuleIndex = $index
}
$index++
}
This implementation ensures that when $score equals $bestScore, the comparison of $index against $bestRuleIndex enforces the file-order tie-breaker.
Configuration in routing.json
The skills/config/routing.json file stores the master routing definitions. Each rule object contains:
id: Unique string identifier for secondary tie-breakingkeywords: Array of strings to match against user hintsweights: Optional dictionary mapping keywords to numeric valuesbasePriority: Optional integer added to the final score (defaults to 0)
Maintainers influence routing priority by adjusting these values or repositioning rules within the JSON array.
Testing the Scoring Logic
The skills/scripts/test-routing.sh and skills/scripts/test-routing.ps1 scripts validate the scoring algorithm across multiple scenarios. These test suites verify deterministic behavior when rules achieve matching scores, ensuring the tie-breaking logic remains consistent across platforms and under load.
Summary
- Score calculation: Sum of (keyword weight × match count) plus basePriority
- Default values: Unspecified weights default to 1; unspecified basePriority defaults to 0
- Primary tie-breaker: Array index in
skills/config/routing.json(lower index wins) - Secondary tie-breaker: Alphabetical ordering of rule
idfields - Implementation location:
skills/scripts/verify-routing-coherence.ps1contains the runtime logic - Configuration location:
skills/config/routing.jsondefines rules, keywords, weights, and priorities
Frequently Asked Questions
What is the default weight for keywords in reverse-skill routing?
When a rule does not specify a custom weight for a keyword in its weights dictionary, the system assigns a default weight of 1. This value is applied in skills/scripts/verify-routing-coherence.ps1 using the null-coalescing operator (?? 1).
How does basePriority differ from keyword weights?
basePriority is a static integer added once to the rule's total score regardless of how many keywords match, while keyword weights are multiplied by match counts. Use basePriority to favor specific rules globally; use weights to reward specific keyword matches differentially.
What happens if two rules have identical scores and the same index?
If two rules achieve the same score and share the same position index (rare but possible with dynamic configurations), the router compares their id fields lexicographically. The rule with the alphabetically first id string wins, as implemented in the secondary tie-breaker logic.
Where is the routing configuration stored?
The master routing configuration resides in skills/config/routing.json. This file contains all rule definitions, keyword arrays, weight modifiers, and base priority values. The skills/routing.md file provides human-readable documentation for maintainers editing this configuration.
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 →