worldbox-observer-mod/docs/event-observation.md

1.7 KiB

Event observation (observe → confirm → emit)

IdleSpectator learns about the game through Harmony sensors. Those sensors must not treat AI noise as catalog truth.

Pipeline

Patch (Observe)  →  EventOutcome (Confirm)  →  Feed Emit (EventReason + catalog)
Layer Responsibility Lives in
Observe Thin Harmony Prefix/Postfix; snapshot before when needed Events/Patches/*
Confirm Did the semantic claim happen? Events/EventOutcome.cs
Bridge Drop unconfirmed with InterestDropLog; else run emit Events/EventObservation.cs
Emit Catalog dials, keys, EventReason labels Events/Feeds/*

Rules

  1. Never treat BehResult.Continue as success by itself.
  2. Prefer state setters when they exist (setLover, setParent*, newFamily, addNewStatusEffect).
  3. Beh hooks need before/after confirmation (EventOutcome.GainedFamily, StillSeekingLover, …).
  4. Unconfirmed attempts log outcome_unconfirmed via InterestDropLog (not silent).
  5. New catalog events must name their confirm predicate (or setter) in the audit TSV game_call_site / fix_action.

Example (family join)

Vanilla BehFamilyGroupJoin returns Continue even when no nearby family exists. Confirm with GainedFamily(before, actor) before Emit family_group_join.

Adding an event

  1. Find the real game call site (setter or Beh).
  2. Add/extend an EventOutcome predicate if needed.
  3. Patch calls EventObservation.Confirm / ConfirmAfter then the domain feed.
  4. Mark the audit row with the confirm rule.
  5. Harness: force or live path that asserts key + absence when outcome fails.