In naive LLM simulations, entities magically know things they shouldn’t:
Temporal Anachronism
Character references future event that hasn’t happened yet
Information Telepathy
Character knows private conversation they didn’t witness
Source Amnesia
Character states fact with no traceable origin
Omniscient Entities
All characters share narrator’s knowledge
The fundamental insight: Entities shouldn’t magically know things. Every piece of knowledge should have a traceable origin—who learned what, from whom, when, with what confidence.
An exposure event is a logged record of knowledge acquisition:
ExposureEvent: entity_id: str # Who learned event_type: EventType # How they learned information: str # What they learned source: Optional[str] # From whom/what timestamp: datetime # When confidence: float # How certain (0.0-1.0) timepoint_id: str # Where in causal chain
Entity directly observed an eventExample: “Madison witnessed Washington’s speech at convention”Confidence: High (0.9-1.0)
Entity acquired information through study/readingExample: “Jefferson learned of Shays’ Rebellion from newspapers”Confidence: Medium-High (0.7-0.9)
Entity was explicitly informed by another entityExample: “Franklin told Madison about Pennsylvania’s constitution”Confidence: Medium (0.6-0.8), depends on source trust
Entity lived through an event personallyExample: “Hamilton experienced combat at Yorktown”Confidence: Very High (0.95-1.0)
Iron Law: entity.knowledge_state ⊆ {e.information for e in entity.exposure_events where e.timestamp ≤ query_timestamp}An entity cannot know something without a recorded exposure event explaining how they learned it.
ExposureEvent( entity_id="james_madison", event_type="experienced", information="Virginia Plan constitutional framework", source="self", # Madison is the creator timestamp="1787-05-14", confidence=1.0, timepoint_id="virginia_plan_drafting")
2
May 25: Madison Shares with Washington
# Madison's tellingExposureEvent( entity_id="george_washington", event_type="told", information="Virginia Plan constitutional framework", source="james_madison", timestamp="1787-05-25", confidence=0.85, # Trust in Madison timepoint_id="washington_madison_meeting")
3
May 29: Washington References Plan ✅
# VALID: Washington has exposure from Step 2dialog_turn = DialogTurn( speaker="george_washington", content="As Madison's proposal outlines, we need strong federal powers", knowledge_references=["Virginia Plan constitutional framework"], timestamp="1787-05-29")# Validation passes:knowledge_accessible = check_exposure_events( entity="george_washington", knowledge="Virginia Plan constitutional framework", query_time="1787-05-29")# → Returns exposure from May 25
4
May 29: Jefferson References Plan ❌
# INVALID: Jefferson not present, no exposuredialog_turn = DialogTurn( speaker="thomas_jefferson", content="Madison's Virginia Plan is too centralist", knowledge_references=["Virginia Plan constitutional framework"], timestamp="1787-05-29")# Validation FAILS:knowledge_accessible = check_exposure_events( entity="thomas_jefferson", knowledge="Virginia Plan constitutional framework", query_time="1787-05-29")# → No exposure events found# → ValidationError: Temporal anachronism detected
Jefferson was in Paris as ambassador during the convention. He cannot know about internal deliberations.
Example: What if Madison had not shared with Washington?
# Remove the exposure eventstore.delete_exposure_event( entity_id="george_washington", information="Virginia Plan constitutional framework", timestamp="1787-05-25")# Re-run simulation from May 26 forwardbranch = create_counterfactual_branch( parent_timeline=baseline, intervention_point="may_25_meeting", intervention=Intervention( type="knowledge_removal", target="george_washington", parameters={"knowledge": "Virginia Plan constitutional framework"} ))# Washington's May 29 dialog now CANNOT reference Virginia Plan# System generates alternative dialog without that knowledge
This enables causal impact analysis: How much did this specific knowledge transfer matter?
# BROKEN: Naive extractiondef extract_knowledge_references(content: str) -> List[str]: words = content.split() knowledge_items = [] for word in words: clean = word.strip('.,!?;:"\'-()[]{}') if clean and len(clean) > 3 and clean[0].isupper(): knowledge_items.append(clean.lower()) return list(set(knowledge_items))# Result from dialog:# ["we'll", "thanks", "what", "michael", "i've"] # GARBAGE
This catches sentence-initial words, contractions, common words, names without context—all useless.
def validate_behavior(entity, new_behavior, timespan): old_traits = entity.behavior_vector new_traits = new_behavior.behavior_vector delta = np.linalg.norm(new_traits - old_traits) max_change = 0.1 * timespan.days # 10% per day max return ValidationResult( valid=delta <= max_change, violations=[f"Behavior shift too rapid: {delta:.2f} > {max_change:.2f}"] )
Analogy: Momentum—entities have inertia, can’t change direction instantly
4. Biological Constraints
Law: Physical limitations constrain behavior
def validate_biological(entity, action): violations = [] if action.requires_mobility and entity.physical_tensor.mobility < 0.3: violations.append("Action requires mobility entity lacks") if action.location_required and entity.physical_tensor.location != action.location: violations.append("Entity not at required location") return ValidationResult( valid=len(violations) == 0, violations=violations )
Analogy: Physical constraints are hard limits
5. Network Flow
Law: Information propagates along relationship edges
def validate_network_flow(knowledge_item, source, target, graph): # Check if path exists in relationship graph path = nx.shortest_path(graph, source, target) if not path: return ValidationResult( valid=False, violations=[f"No information path from {source} to {target}"] ) # Check trust levels along path min_trust = min(graph[u][v]["trust_level"] for u, v in zip(path[:-1], path[1:])) return ValidationResult( valid=min_trust > 0.3, # Threshold for information flow violations=[f"Trust too low along path: {min_trust:.2f}"] )
Analogy: Information flows like water through pipes (relationship network)
# Doctor wants to use cave shelter discovered by separate exploration teamvalidate_information(okonkwo, {"knowledge": "cave_shelter_location"})# ❌ No exposure eventvalidate_network_flow("cave_shelter_location", source="scout_team", target="okonkwo", graph)# ❌ Scout team has not returned to base yet (Day 9)# ❌ No communication link establishedValidationResult( valid=False, violations=["Knowledge not accessible: no exposure or communication path"])# Doctor cannot reference cave shelter until scouts return
Important: Specific numerical values (O₂ rates, radiation levels, etc.) in simulation output are LLM-generated narrative, not computed by the engine. The engine enforces structural constraints (information conservation, energy budgets, behavioral inertia), not physics calculations.
In PORTAL mode (backward reasoning), characters exist at multiple timepoints but with different causal positions. A character in 2028 cannot know about events from 2030 in their past.
def filter_knowledge_by_causal_time(entity, timepoint, store): """Remove knowledge from causally inaccessible timepoints.""" # Walk causal_parent chain to build ancestor set ancestors = set() current = timepoint while current: ancestors.add(current.timepoint_id) parent_id = current.causal_parent current = store.get_timepoint(parent_id) if parent_id else None # Filter exposure events to only ancestors accessible_events = [ e for e in store.get_exposure_events(entity.entity_id) if e.timepoint_id in ancestors ] return accessible_events
Example: Portal Mode Character in 2028
Scenario: Presidential campaign portal, endpoint 2040, character at 2028 stepFull Knowledge Graph:
“Campaign strategy meeting July 2027” ✅ Accessible
“Primary victory March 2028” ✅ Accessible
“Running mate selection June 2029” ❌ Not yet happened
“General election debate Oct 2029” ❌ Not yet happened
“Inauguration January 2040” ❌ Endpoint, not accessible
Filtered Knowledge (what character actually knows in 2028):
Campaign strategy
Primary victory
Dialog Generation: Uses only filtered knowledge, character cannot reference or fear events from 2029+