# Entity Knowledge Attributes Canonical keys for the `EntityKnowledge.known_attributes` BTreeMap (defined in `server/src/knowledge/types.rs`). These keys structure what one entity knows about another. ## Overview `EntityKnowledge.known_attributes` is a `BTreeMap` — key-value pairs where: - **Key**: Structured attribute name (defined below) - **Value**: String representation of the attribute The knowledge graph uses these attributes to determine: - What the observer's monologue says about the target - Which dialogue lines are available - How the target renders in the observer snapshot (name vs. description) - Whether secrets or contradictions are discovered --- ## Identity Attributes ### `name` **Value format**: Full name as known to the observer. **Examples**: - `"Kael Davan"` — observer knows full name - `"Kael"` — observer knows first name only - `"the dock worker"` — observer doesn't know name, only role **Usage**: Monologue and dialogue rendering. If `name` is absent or generic, monologue says "the dock worker" instead of "Kael." --- ### `role` **Value format**: Occupational or social role. **Examples**: - `"dock worker"` - `"shift supervisor"` - `"bartender"` - `"off-duty security"` - `"ring coordinator"` (if known) **Usage**: Default descriptor when name is unknown. Access tier calculation (authority figures get different treatment). --- ### `faction` **Value format**: Institutional or organizational allegiance. **Examples**: - `"Commission"` — Sera, Torek, Detective - `"civilian"` — most NPCs - `"ring member"` — if discovered - `"unknown"` — not yet determined **Usage**: Access tier logic. Commission-tagged individuals trigger different NPC behavior. Dialogue selection uses this for authority/peer filtering. --- ### `species` **Value format**: Species identifier (future-proofing — v0.1 is all human). **Examples**: - `"human"` (default) - (Future: other species as defined) **Usage**: Not load-bearing in v0.1. Placeholder for future non-human NPCs. --- ## Social Attributes ### `relationship_type` **Value format**: Relationship category from observer's perspective. **Examples**: - `"colleague"` — Kael to smuggler - `"friend"` — Sera to detective - `"authority figure"` — Voss to subordinates - `"suspect"` — Kael to detective (post-discovery) - `"partner"` — Hael to Kael - `"stranger"` — new NPCs **Usage**: Drives `RelationshipState` calculation (Unknown/Known/Friendly/PersonOfInterest/Hostile). Determines emotional tone of monologue. --- ### `trust_level` **Value format**: Trust assessment (subjective, observer's judgment). **Examples**: - `"trusted"` — high trust, shares sensitive information - `"reliable"` — professional trust - `"uncertain"` — cautiously neutral - `"suspicious"` — flagged for observation - `"compromised"` — known to be under pressure or bought **Usage**: Gates trust-tier dialogue (surface/real/secret). Detective tracking trust levels determines which NPCs can be turned. --- ## Behavioral Attributes ### `routine_pattern` **Value format**: Observed routine description. **Examples**: - `"morning shift at logistics hub, bar after shift"` - `"arrives 06:00, break 10:30, departs 14:00"` - `"irregular schedule, seen at odd hours"` **Usage**: Deviation detection. When current behavior doesn't match known `routine_pattern`, monologue flags it. --- ### `behavior_flags` **Value format**: Comma-separated behavioral observations. **Examples**: - `"nervous,lattice_checking"` — Kael during contradiction arc - `"avoidance_pattern,evasive"` — Sera avoiding Torek - `"spending_beyond_means"` — Torek buying rounds - `"reliable,punctual"` — baseline normal behavior **Usage**: Tell system. Multiple flags accumulate as evidence. Detective's analytical lattice auto-flags some behaviors. --- ## Secret Attributes ### `secret_held` **Value format**: What the observer believes this entity is hiding. **Examples**: - `"ring membership"` — detective's suspicion about Kael - `"unreported evidence"` — smuggler's read on Sera (if observant) - `"gambling debt"` — if Drin's vulnerability is discovered - `"exit attempt"` — if Kael's unauthorized contact is discovered **Usage**: Drives PersonOfInterest state. Gates confrontation dialogue. Smuggler and detective track different secrets about the same NPCs. --- ### `secret_confidence` **Value format**: How certain the observer is about the secret. **Examples**: - `"suspected"` — behavioral flags suggest something, no proof - `"likely"` — multiple indicators align - `"confirmed"` — direct evidence or confession **Usage**: Dialogue tone. "Suspected" secrets allow fishing questions. "Confirmed" secrets enable direct confrontation. --- ## Investigation Attributes (Detective-Specific) ### `tell_observed` **Value format**: Specific tell noted by the detective. **Examples**: - `"looks left when lying"` — Kael's tell - `"leaves when Torek arrives"` — Sera's avoidance - `"checks lattice before answering"` — nervous behavior - `"forced casualness after shift supervisor passes"` — hypervigilance **Usage**: Behavioral profiling. Accumulated tells build case strength. Monologue references specific tells when they recur. --- ### `contradiction_flagged` **Value format**: Boolean-ish flag (presence of key = true). **Examples**: - `"meeting_unknown_contact"` — Kael contradiction - `"avoidance_inconsistency"` — Sera contradiction - `"manifest_access_mismatch"` — Maret handling cargo she shouldn't process **Usage**: THE FRIEND arc trigger. When this attribute is set, monologue tone shifts. Dialogue options change. RelationshipState moves toward PersonOfInterest. --- ## Examples: Full EntityKnowledge Entries ### Smuggler's knowledge of Kael (early game, pre-contradiction) ```rust EntityKnowledge { last_known_position: Some(TilePosition { x: 45, y: 12 }), // logistics hub dock last_observed_tick: 1200, last_updated_tick: 1200, confidence: KnowledgeConfidence::Direct, // currently in LOS source: KnowledgeSource::DirectObservation { tick: 1200 }, state: KnowledgeState::Active, relationship: RelationshipState::Friendly, known_attributes: BTreeMap::from([ ("name".to_string(), "Kael Davan".to_string()), ("role".to_string(), "dock worker".to_string()), ("faction".to_string(), "ring member".to_string()), // smuggler knows ("species".to_string(), "human".to_string()), ("relationship_type".to_string(), "close colleague".to_string()), ("trust_level".to_string(), "trusted".to_string()), ("routine_pattern".to_string(), "morning shift 06:00-14:00, bar after shift".to_string()), ("behavior_flags".to_string(), "reliable,punctual".to_string()), ]), } ``` ### Detective's knowledge of Kael (mid-game, post-contradiction discovery) ```rust EntityKnowledge { last_known_position: Some(TilePosition { x: 45, y: 12 }), last_observed_tick: 2400, last_updated_tick: 2600, // updated via inference after observation confidence: KnowledgeConfidence::KnowsDetails, // not currently in LOS, but detailed knowledge source: KnowledgeSource::Inferred { basis: vec![ FactId("investigation.manifest_discrepancy".to_string()), FactId("investigation.shift_mismatch".to_string()), ], }, state: KnowledgeState::Active, relationship: RelationshipState::PersonOfInterest, // flagged known_attributes: BTreeMap::from([ ("name".to_string(), "Kael Davan".to_string()), ("role".to_string(), "dock worker".to_string()), ("faction".to_string(), "civilian".to_string()), // detective doesn't know ring membership yet ("species".to_string(), "human".to_string()), ("relationship_type".to_string(), "suspect".to_string()), ("trust_level".to_string(), "suspicious".to_string()), ("routine_pattern".to_string(), "morning shift, frequent late departures".to_string()), ("behavior_flags".to_string(), "nervous,lattice_checking,evasive".to_string()), ("tell_observed".to_string(), "looks left when lying".to_string()), ("secret_held".to_string(), "unauthorized meetings".to_string()), ("secret_confidence".to_string(), "confirmed".to_string()), ("contradiction_flagged".to_string(), "meeting_unknown_contact".to_string()), ]), } ``` ### Smuggler's knowledge of Sera (if observant, mid-game) ```rust EntityKnowledge { last_known_position: Some(TilePosition { x: 78, y: 34 }), // bar last_observed_tick: 1800, last_updated_tick: 2100, confidence: KnowledgeConfidence::KnowsOf, source: KnowledgeSource::DirectObservation { tick: 1800 }, state: KnowledgeState::Active, relationship: RelationshipState::Known, // not Friendly -- smuggler doesn't know Sera well known_attributes: BTreeMap::from([ ("name".to_string(), "Sera Venn".to_string()), ("role".to_string(), "Commission field tech".to_string()), ("faction".to_string(), "Commission".to_string()), ("species".to_string(), "human".to_string()), ("relationship_type".to_string(), "institutional presence".to_string()), ("trust_level".to_string(), "uncertain".to_string()), ("routine_pattern".to_string(), "bar regular, off-duty evenings".to_string()), ("behavior_flags".to_string(), "observant,avoidance_pattern".to_string()), ("secret_held".to_string(), "knows something about Torek or Hael".to_string()), ("secret_confidence".to_string(), "suspected".to_string()), ]), } ``` --- ## Attribute Lifecycle 1. **Initial state** (Unknown NPC): No attributes. EntityKnowledge doesn't exist yet. 2. **First observation** (Direct confidence): `name` (if visible via lattice query or introduction), `role` (inferred from context), `species`, `routine_pattern` starts accumulating. 3. **Repeated interaction** (KnowsOf): `relationship_type` evolves, `trust_level` set, `behavior_flags` accumulate. 4. **Investigation depth** (KnowsDetails): `secret_held`, `tell_observed`, `contradiction_flagged` added by detective. Smuggler gains `faction` clarity. 5. **Knowledge decay**: Attributes persist even as confidence decays. A KnowsOf entry retains all attributes; only positional certainty degrades. --- ## Content Authoring Guidance - **Monologue prerequisites** can reference specific attributes: `known_attributes["secret_held"] == "ring membership"`. - **Dialogue access tiers** can check `faction` or `relationship_type`. - **Tell system observations** append to `behavior_flags` as comma-separated values. - **THE FRIEND contradiction** is triggered by setting `contradiction_flagged`. --- **Total canonical keys**: 14 (4 identity, 2 social, 2 behavioral, 2 secret, 2 investigation, 2 detective-specific). Additional keys can be added as needed, but these 14 cover v0.1 requirements.