Specificity
Selecting the best match when multiple capabilities qualify
When Specificity Matters
A request often matches more than one capability. A request for op=extract
might match both a generic extractor and a PDF-specific extractor. Specificity
determines which one wins: the more constrained capability is preferred because
it was designed for a narrower use case.
Specificity only matters among capabilities that already match the request. A capability that doesn't match is never considered, regardless of its specificity score.
Graded Scoring
Each tag in a capability URN gets a score based on how constrained it is. More constrained tags score higher.
| Value type | Score | Why |
|---|---|---|
Exact value (K=v) |
3 | Most constrained — requires a specific value |
Must-have-any (K=*) |
2 | Requires presence but allows any value |
Must-not-have (K=!) |
1 | Constrains by exclusion |
Unspecified (K=? or missing) |
0 | No constraint at all |
The total specificity of a capability is the sum of all its tag scores.
# cap:op=extract # op=extract: exact value = 3 # Total: 3 # cap:format=pdf;op=extract # op=extract: 3, format=pdf: 3 # Total: 6 # cap:format=*;op=extract # op=extract: 3, format=*: 2 # Total: 5 # cap:debug=!;format=pdf;op=extract # op=extract: 3, format=pdf: 3, debug=!: 1 # Total: 7
Direction Spec Scoring
The in and out tags are special. Instead of getting
the flat score of 3 (exact value), they contribute their Media URN's tag count.
A Media URN with more tags is more specific because it describes a narrower
data format.
# Counting Media URN tags: media:bytes # 1 tag media:pdf;bytes # 2 tags media:image;png;bytes # 3 tags media:image;png;bytes;thumbnail # 4 tags
A capability with in="media:pdf;bytes" is more specific than one
with in="media:bytes". The first requires PDF files; the second
accepts any bytes. Both match a request for PDF bytes, but the first one is
the better fit.
# Two matching capabilities for a PDF extraction request: # Cap A: cap:in="media:bytes";op=extract;out="media:text;utf8" # in: 1 tag, op: 3, out: 2 # Total: 6 # Cap B: cap:in="media:pdf;bytes";op=extract;out="media:text;utf8" # in: 2 tags, op: 3, out: 2 # Total: 7 (wins)
Worked Example
A request asks for Spanish translation: cap:language=es;op=translate.
Three capabilities match:
# Request: cap:language=es;op=translate # Cap A: cap:op=translate # op=translate: 3 # Total: 3 # Cap B: cap:language=*;op=translate # op=translate: 3, language=*: 2 # Total: 5 # Cap C: cap:language=es;op=translate # op=translate: 3, language=es: 3 # Total: 6
All three match the request (see Matching for why). Cap C wins with a score of 6 because it specifies the exact language. Cap B is second because it at least requires a language to be specified. Cap A is least specific — it matches any translation request.
This is the right behavior. When you ask for a Spanish translator, you want the one built for Spanish, not a generic translator that happens to also work.
Worked Example: Direction Specs
A request asks for thumbnail generation from a PDF:
Request: cap:in="media:pdf;bytes";op=thumbnail;out="media:image;bytes"
Two capabilities match:
# Cap A: cap:in="media:bytes";op=thumbnail;out="media:image;png;bytes;thumbnail" # in: 1 tag (bytes) # op: 3 # out: 4 tags (image, png, bytes, thumbnail) # Total: 8 # Cap B: cap:in="media:pdf;bytes";op=thumbnail;out="media:image;png;bytes" # in: 2 tags (pdf, bytes) # op: 3 # out: 3 tags (image, png, bytes) # Total: 8
Both score 8. This is a tie, resolved by tie-breaking rules.
Tie-Breaking
When two capabilities have the same total specificity score, they are compared using a tuple of counts:
- Exact value count — number of tags with exact values (
K=v) - Must-have-any count — number of tags with
K=* - Must-not-have count — number of tags with
K=!
The tuple is compared lexicographically: first by exact count, then by must-have-any count, then by must-not-have count. More exact values win.
# Same total score of 5: # Cap A: cap:format=*;op=extract;target=* # Exact: 1 (op), Must-have-any: 2 (format, target) # Tuple: (1, 2, 0) # Cap B: cap:format=pdf;op=extract # Exact: 2 (op, format), Must-have-any: 0 # Tuple: (2, 0, 0) ← wins (more exact values)
If the tuple is also tied, the capability that was registered first wins. This provides a stable, deterministic ordering.
Summary
- Specificity only applies to capabilities that already match
- Each tag scores: exact=3, must-have-any=2, must-not-have=1, unspecified=0
- Direction specs (
in/out) score by their Media URN tag count - Highest total score wins
- Ties broken by (exact_count, must_have_any_count, must_not_have_count)
- Final tiebreaker: registration order