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

2.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, setFamily, 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.

Negative harness: Beh Continue with no family gain must log outcome_unconfirmed and must not register rel:family_group_join.

Adding an event

For every new camera-worthy catalog id, record three things up front:

Field Meaning Example
Confirm predicate EventOutcome helper, or “setter is the transition” GainedFamily, setLover(null)
Fire API Vanilla call the live harness will invoke BehFamilyGroupLeave.execute, Actor.addTrait
Expected live level Honest target after the runner claims id, id_drop, pipeline (shared=…), or unsupported

Then implement:

  1. Find the real game call site (setter or Beh).
  2. Add/extend an EventOutcome predicate if Beh Continue is ambiguous.
  3. Patch calls EventObservation.Confirm / ConfirmAfter then the domain feed.
  4. Mark the audit row with the confirm rule (event-trigger-audit.tsv = design/call-site only).
  5. Harness: live path asserts key or authored drop; assert absence / outcome_unconfirmed when the outcome fails.
  6. Do not call domain_feed / inject and label it live.
  7. Live proof lands in .harness/event-live-coverage.tsv via EventLiveCoverageLedger.Claim - that file is the source of truth for live levels, not the audit TSV.

See event-live-verification-plan.md for claiming rules and suite wiring.