cap:
Browse Sign In

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 typeScoreWhy
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:

  1. Exact value count — number of tags with exact values (K=v)
  2. Must-have-any count — number of tags with K=*
  3. 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