Affinity and Nemeses
Affinity is the one-to-one projection of the same event stream that feeds reputation: a directed edge from actor to target, moved by the per-event deltas in the domain config, decaying toward the configured neutral point, and labeled with a relationship state from the domain's ladder.
Reading edges
snug reputation affinity get --domain tavern \
--from auth_user:docs-wave --to auth_user:vendor
snug reputation affinity edges --domain tavern \
--entity auth_user:docs-wave --sort negative --limit 10An edge that has never been touched is 404 affinity_not_found. Edges are
directed: the gift you gave the vendor moves you -> vendor, not the
reverse. edges lists an entity's strongest outgoing edges - positive
for top friends, negative for top enemies - from a maintained index
(capped per entity; see the configuration reference). The edge payload
carries the decayed score, the current state, and the state history:
{
"edge": {
"domain": "docs4-tavern",
"from": { "kind": "auth_user", "id": "docs-wave" },
"to": { "kind": "auth_user", "id": "docs4-vendor" },
"score": 3.9999255057288954,
"state": "stranger",
"state_history": [ { "state": "stranger", "entered_at": "2026-08-28T14:16:06.753783Z" } ],
"nemesis": null,
...
}
}The state ladder
Relationship states are inclusive upper bounds, checked in order, so a
ladder like nemesis (-50) / rival (-10) / stranger (10) / friend (50)
labels an edge by where its score falls. Crossing a boundary during
ingestion returns a relationship_transition in the event response and
fans out a relationship_changed transition event. One
-30 event moved a fresh edge stranger -> rival, a second moved it
rival -> nemesis.
Preference profiles
A target's preference profile multiplies affinity deltas for events that
match, optionally on a metadata key/value (requires reputation_granter
or admin to set):
snug reputation preferences set --domain tavern \
--entity auth_user:vendor --file ./prefs.json{
"preferences": [
{ "event_type": "gift_given", "metadata_key": "flower",
"metadata_value": "rose", "delta_multiplier": 3.0 }
]
}Verified: with that profile, a gift_given event carrying
"metadata": {"flower": "rose"} applied +15 to the edge instead of the
base +5. event send has no metadata flag - attach metadata via the batch
file or the raw HTTP body. A rule without metadata_key/metadata_value
multiplies every event of its type. Preferences scale affinity deltas
only, never the reputation score.
Nemesis promotion
A state marked "nemesis_suite": true in the domain config is special:
when an edge falls into it, the transition reports
"nemesis_promoted": true, a nemesis transition event fans out, and the
edge grows a nemesis block - escalation level, victory/defeat counts, and
a bounded memory of the events that forged the rivalry. The target's
roster lists everyone currently holding a nemesis-state edge against them:
snug reputation nemesis list --domain tavern --entity auth_user:docs-wave{
"count": 1,
"nemeses": [
{
"edge": {
"from": { "kind": "ecs_entity", "id": "docs4-npc-guard" },
"to": { "kind": "auth_user", "id": "docs-wave" },
"score": -60.0,
"state": "nemesis",
"nemesis": {
"level": 1, "victories": 0, "defeats": 0,
"memories": [ { "event_type": "ambushed", "summary": "ambushed event",
"weight": 1.0, "occurred_at": "2026-08-28T14:17:04.445485Z" } ],
...
}
},
"level": 1
}
]
}Resolving a rivalry
Rivalries do not decay away on their own - they end deliberately
(requires reputation_granter or admin):
snug reputation nemesis resolve --domain tavern \
--from ecs_entity:docs4-npc-guard --to auth_user:docs-wave \
--outcome reconciledreconciled re-labels the edge stranger; nemesis_defeated_final
re-labels it rival. Either way the nemesis block is archived and removed
from the roster. Verified: the resolved edge came back
"state": "stranger", "nemesis": null with its numeric score untouched at
-60.0 - resolution rewrites the label, then ordinary decay toward neutral
does the rest. Resolving an edge with no active nemesis block is
404 nemesis_not_found (verified by resolving twice).
The exact parameters and schemas for every operation here are in the Reputation API reference.