Skip to content

v0.1 spec

Six design decisions (not research questions — see docs/decisions/open-questions.md) that gate the first code milestone. Adopted below.

1. World scope

Whiterun hold only — the north-star scenario's own setting (docs/vision.md), roughly 20-30 named NPCs (the court: Balgruuf, Proventus, Irileth, Vignar, Hrongar; guards; merchants: Belethor, Arcadia, the Battle-Born/Grey-Mane feud households; innkeeper Hulda; a handful of commoners). Not all ~1,000 — that's the eventual math-tier target, but proving the cascade on a small, hand-known cast is faster to build, faster to eyeball-verify in the dashboard, and the sparse-graph/ observer-local-reputation rules (ADR-0006) don't get easier at scale, so nothing about proving them requires scale yet.

2. Minimum cascade event set

The three event types already in chronicle/events.py are sufficient — no fourth type needed for v0.1:

  • NPCDied — the triggering event.
  • CrimeWitnessed — seeds suspicion (not certainty) about who did it.
  • RumorHeard — carries the story onward, with mutation happening at the claim/variant layer, not by changing the event itself.

Conversation-tier events (player statements) stay deferred with the LLM tiers, per the build order in docs/architecture.md.

3. First player-visible (v0.1: dashboard-visible) payoff

A headless scenario, asserted in scenarios/: Jarl Balgruuf dies → witnesses form high-confidence beliefs, others form low-confidence rumor-sourced beliefs → the story mutates in at least one concrete way as it crosses 2+ retellings → for any NPC's belief, the dashboard's causality-timeline can answer "since when, from what evidence, through whom" by walking Evidence → Claim/Variant → originating Event (ADR-0007). Succession/guard-patrol consequences are not required for v0.1 — they're the acceptance test for the whole architecture eventually, but belief formation + mutation + inspectability is the provable slice now.

4. Rule budget (~20 rules for v0.1)

  1. Witnessing an event creates a Claim plus a witnessed-type Evidence plus a high-confidence BeliefInstance for the witness.
  2. Rumor propagation requires a sampled encounter (shared location + schedule overlap) — never a global broadcast.
  3. Each retelling has a mutation probability, not certainty of mutation.
  4. Mutation changes exactly one typed claim slot per retelling (e.g. perpetrator, cause, location) — never a full rewrite.
  5. Verbatim strength decays faster than gist strength (fuzzy-trace theory), per docs/architecture.md's bounded-memory item.
  6. Confidence decays with time since last rehearsal.
  7. Confidence rises with distinct corroborating source count, not repetition count from the same source.
  8. A grudge is created only when the holder has an existing relationship edge to the victim (sparse-graph rule, ADR-0006) — never unconditionally.
  9. Grudge severity scales with relationship closeness + evidentiary strength, not a flat penalty.
  10. Reputation updates are observer-local ((observer, subject, context)) — never a global score (ADR-0006).
  11. Relationship edges are created only via co-location, kinship, faction, or shared employer — never for an arbitrary pair.
  12. Canonical claims never mutate in place; a mutation always produces a new Variant linked to its predecessor.
  13. Every BeliefInstance must resolve to an evidence chain back to a canonical event (ADR-0007) — no orphan beliefs.
  14. CrimeWitnessed with no confirmed perpetrator seeds suspicion, not a named-culprit belief, until testimony accumulates.
  15. Encounter sampling draws from NPC schedules — no "everyone within N ticks" shortcut.
  16. Rumor stage machine: unheard -> heard -> repeated -> dormant -> forgotten.
  17. EventLog.append()'s idempotency guarantee is relied on, not re-implemented, at the claim layer.
  18. Obligations, grudges, and reputation stay three separate record kinds — never merged (ADR-0006).
  19. Belief derivation is lazy/cached per ADR-0006's consequence, not eagerly maintained on every tick.
  20. No adapters/skyrim/ code is touched until this scenario suite is green headless.
  21. Two witnesses to the same canonical event share one Claim record (looked up by canonical_event_key), not one independent claim each — a second witness's disagreement belongs on their own Variant/belief, never on a second, differently-worded canonical claim for the same event (rule 12's immutability guarantee would otherwise be defeated at the store level, not just the object level). Enforced by ClaimStore.witness().

5. Rumor representation

Typed claim slots (Claim(kind, slots)), not a feature-vector. Slots are named and typed per claim kind (e.g. a death claim has perpetrator, cause, location slots) — this is what makes rule 4 above ("mutate exactly one slot") and rule 13 (evidence-chain inspectability) implementable without inferring structure from a vector.

6. Headless duration

Stay headless through the entirety of the claim/variant + belief + evidence-chain scenario suite (rules 1-19 above, demonstrated by the payoff in §3). adapters/skyrim/ isn't touched until that suite is green — matches the existing status line in README.md and docs/decisions/open-questions.md.

Next

First code milestone: chronicle/claims.pyClaim, Variant, Evidence, BeliefInstance per ADR-0006's record shapes, built on top of the existing EventLog, with a scenario test exercising rules 1, 3, 4, and 13 above (witness -> claim -> mutated variant -> evidence-chain lookup).