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

82 lines
4.5 KiB
Markdown

# Event audit (post-expand)
Inventory policy after the full gap expand.
Camera interrupt is score-margin only (`cutInMargin`); no Signal/Ambient ownership gate.
**Single inventory:** [`EventCatalog`](../IdleSpectator/Events/EventCatalog.cs) (partials under `Events/Catalogs/`).
Nested domains: `Status`, `Happiness`, `WorldLog`, `Trait`, `Combat`, `Spell`, …
Feeds/patches register from those dials; `InterestDirector` only ranks candidates.
## Dials
| Dial | Role |
|------|------|
| `CreatesInterest` | Whether a live id may register at all |
| `EventStrength` | Base contribution to `TotalScore` (interrupt via +`cutInMargin`) |
| `Completion` | Hold-until-complete kind |
| `MaxWatch` | Hard cap (class defaults in `scoring-model.json`) |
| `EventReason` | Orange dossier sentence |
## MaxWatch class defaults
| Class | Seconds | JSON field |
|-------|--------:|------------|
| Moment / FixedDwell | 15 | `maxWatchMoment` |
| Status | 30 | `maxWatchStatus` |
| Grief | 45 | `maxWatchGrief` |
| Combat | 60 | `maxWatchCombat` |
| Epic world | 50 | `maxWatchEpic` |
Peer rotate / soft cut on EventLed floors at `minCameraDwell` (15s). Score-margin interrupts bypass that floor.
Ambient / Character fill is exempt - events may take the camera immediately.
## Sources (wired)
| Source | Primary owner | Reason factory | Notes |
|--------|---------------|----------------|-------|
| WorldLog | `InterestFeeds.OnWorldLogMessage` | catalog / EventReason | Strength from `EventCatalog.WorldLog` |
| Happiness | `IngestHappiness` | `EventCatalog.Happiness` + EventReason | Prose must match game call sites - see [event-prose-audit.md](event-prose-audit.md) |
| Status | `OnStatusChange` | EventReason.Status | `drowning` CreatesInterest=true, strength ~50; notable via CharacterSignificance |
| Scanner combat | WorldActivityScanner | EventReason.Fight / Battle | Completion CombatActive; dials `EventCatalog.Combat` |
| War | WarEventPatches + WarInterestFeed.Tick | war type labels | |
| Plot | PlotEventPatches + PlotInterestFeed.Tick | `EventCatalog.Plot` | |
| Relationship | RelationshipEventPatches + happiness lovers | EventReason.* | |
| Trait | TraitEventPatches | EventReason.Trait | Spawn window filters routine traits |
| Building | BuildingEventPatches | EventReason.Building* | Eat/damage/falls |
| Boat | BoatEventPatches | EventReason.Boat | |
| Book | BookEventPatches | `EventCatalog.Book` sentences | |
| Era / Meta | MetaEventPatches | EventReason.MetaNew / era labels | |
| Spell | CombatActionLibrary.tryToCastSpell | EventReason.Library | Ambient CreatesInterest=false except spectacle ids |
| Power | PlayerControl.clickedFinal | EventReason.HumanizeId | Spectacle ids create interest |
| Decision | setDecisionCooldown | EventReason.Library | IsCameraWorthy filter |
| Item | ItemManager | EventReason.Library | Legendary CreatesInterest |
| Gene | Subspecies.mutateFrom | EventReason.Library | Ambient CreatesInterest=false |
| Phenotype | generatePhenotypeAndShade | EventReason.Library | |
| World law | WorldLaws.enable / toggle | EventReason.HumanizeId | Location-only |
| Biome | catalog ready | EventReason.HumanizeId | Ambient CreatesInterest=false; emit via power terraform path |
| Subspecies trait | SubspeciesManager biome hooks | EventReason.Library | |
| Character fill | InterestDirector.TryCharacterFill | empty Label | Only when no pending EventLed |
## Ambient statuses (intentional off)
`festive_spirit`, `laughing`, `singing`, `sleeping`, `handsome_migrant` - CreatesInterest=false.
## Same-moment ownership
Prefer typed feeds over WorldLog when both fire (relationship / status / combat).
Registry Upsert merges same key and refreshes `LastSeenAt` for sticky combat/status/grief.
## Interrupt / hold / grace
1. Instant cut when `next.TotalScore >= current + cutInMargin` (no settle; ignores min dwell).
2. Ambient fill: any EventLed may take the camera immediately (no `minCameraDwell`).
3. Else hold while `InterestCompletion.IsActive` and under MaxWatch (moments floor to `minCameraDwell`; combat uses class 60s).
4. Soft peer rotates on EventLed only after `minCameraDwell` (15s).
5. Quiet grace 6s: still-worth-watching filter, then Character fill with empty reason.
## Mutation gap triage
`mutation_discovery` refreshes `.harness/mutation_gaps.tsv`.
Open rows are unexplained Wire candidates only.
False positives (clear/load/UI/FX/getters) and covered-by-primary paths are filtered or listed in `AlreadyWired`.
Library fields are inventory-complete via catalogs / activity / WorldLog (`mutation_libraries.tsv` notes).