93 lines
4.8 KiB
Markdown
93 lines
4.8 KiB
Markdown
# Event audit (A/B layers)
|
|
|
|
**Layer B (ticker):** Activity / Life coverage for live library ids - honest prose, completeness.
|
|
**Layer A (story camera):** only `EventCatalog.IsCameraWorthy` beats register interest and cut the camera.
|
|
|
|
**Single inventory:** [`EventCatalog`](../IdleSpectator/Events/EventCatalog.cs) (partials under `Events/Catalogs/`).
|
|
Feeds/patches register A from those dials; `InterestDirector` only ranks candidates.
|
|
|
|
## Dials
|
|
|
|
| Dial | Layer | Role |
|
|
|------|-------|------|
|
|
| Happiness `Presentation` | A if Signal | Ambient/Aggregate = B-only |
|
|
| `CreatesInterest` | A gate | Discrete / status / WorldLog / libraries |
|
|
| `EventStrength` | A rank | Base `TotalScore` (interrupt via margin) |
|
|
| `Completion` | A hold | Hold-until-complete kind |
|
|
| `MaxWatch` | A hold | Hard cap (`scoring-model.json`) |
|
|
| `EventReason` / Label | A display | 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; sticky A scenes use `stickyCutInMargin`.
|
|
Ambient / Character fill is exempt - A events may take the camera immediately.
|
|
|
|
## Sources (wired)
|
|
|
|
| Source | Primary owner | Reason factory | Notes |
|
|
|--------|---------------|----------------|-------|
|
|
| WorldLog | `InterestFeeds.OnWorldLogMessage` | catalog / EventReason | A if CreatesInterest |
|
|
| Happiness | `IngestHappiness` | catalog + EventReason | Signal = A; see [event-prose-audit.md](event-prose-audit.md) |
|
|
| Status | `OnStatusChange` | EventReason.Status | Gain A if CreatesInterest; egg **loss** → hatch A |
|
|
| Scanner combat | WorldActivityScanner | EventReason.Fight / Battle | `EventCatalog.Combat` |
|
|
| War / Plot / Relationship / Trait / Building / Boat / Book / Era / Kingdom | Feeds + patches | EventReason / catalog | A via CreatesInterest; alpha via Family.setAlpha |
|
|
| Libraries | Deferred feeds | EventReason.Library | Mostly B; spectacle ids A |
|
|
| Character fill | InterestDirector.TryCharacterFill | empty Label | Only when no pending EventLed |
|
|
|
|
## Layer A policy
|
|
|
|
Interesting beats register as interest candidates (`Signal` / `CreatesInterest`).
|
|
Director ranks by `EventStrength` + scoring - do not hard-gate interesting life off Layer A.
|
|
|
|
Happiness Ambient (B) only: `got_poked`, `got_caught`, `paid_tax`, `just_ate`, `just_pooped`.
|
|
Happiness Aggregates stay civic mass (B unit camera).
|
|
|
|
Status B: brief FX/cooldowns + egg gain only.
|
|
|
|
Noise still skipped at patch (not dial): building_damage chips, boat_load, **ambient building/object destroy** (falls are Layer B; consume stays A).
|
|
|
|
Presentability: production `EventFeedUtil.Register` rejects Labels the dossier would blank (`unpresentable` drop). See [camera-presentability-plan.md](camera-presentability-plan.md).
|
|
|
|
## Full surface
|
|
|
|
See [world-event-inventory.md](world-event-inventory.md) for live library counts, gaps, and refresh commands.
|
|
|
|
## Interrupt / hold / grace
|
|
|
|
1. Instant cut when `next.TotalScore >= current + cutInMargin` (sticky: `stickyCutInMargin`).
|
|
2. Ambient fill: any A EventLed may take the camera immediately.
|
|
3. Else hold while `InterestCompletion.IsActive` and under MaxWatch.
|
|
4. Soft peer rotates on EventLed only after `minCameraDwell` (15s), never during protected sticky hold without margin.
|
|
5. Quiet grace 6s: still-worth-watching filter, then Character fill with empty reason.
|
|
6. Drops recorded in `InterestDropLog`.
|
|
7. Focus continuity: while Idle Spectator is on, a missing living camera focus is repaired the same director tick (reattach scene follow/related, else ambient fill / any alive unit). Orphan scenes (no living follow/related) end as `follow_lost` instead of sitting in quiet_grace with an empty camera.
|
|
|
|
## Mutation gap triage
|
|
|
|
`mutation_discovery` refreshes `.harness/mutation_gaps.tsv`.
|
|
Open rows are unexplained Wire candidates only.
|
|
|
|
## Idle quality
|
|
|
|
Done (see [camera-presentability-plan.md](camera-presentability-plan.md) and `combat_focus`):
|
|
|
|
- Presentability gate, ambient fall demotion, focus hold, tip placeholder ban
|
|
- Status-overlap hold (onset requires live status; offsets stay FixedDwell)
|
|
- Combat tip/focus alignment (highest-scored participant; tip subject matches focus;
|
|
clears "is fighting" when combat goes cold)
|
|
|
|
Done (0.25.52): dossier nametag tracks focus on handoff (`CameraDirector.Watch` focus-then-caption;
|
|
`WatchCaption.ReconcileDossierToFocus`; `combat_focus` asserts `dossier_matches_focus`).
|
|
|
|
Done (0.25.64): sticky combat handoff on follow_lost + never collapse sticky tips to "X is fighting".
|
|
|
|
Soak audit helper: `./scripts/soak-audit-player-log.sh [seconds]` (or pass `--since-bytes N`).
|