Research index¶
One row per filed report. [BUILD-ON]/[RISK] lists below are merged across
all reports — see each file for full detail and citations.
| # | File | Topic | Sources | Status |
|---|---|---|---|---|
| 01 | 01-skyrim-modding-substrate.md | Skyrim modding substrate (Mantella/CHIM/SkyrimNet/SKSE) | 2 independent reports | filed — contains an unresolved disagreement, see below |
| 02 | 02-social-simulation-literature.md | Social-sim literature for game-scale belief systems | 1 report | filed |
| 03 | 03-hybrid-llm-symbolic-architecture.md | Hybrid LLM + symbolic simulation architectures | 3 reports (high overlap) | filed |
| 04 | 04-voice-pipeline.md | Voice/dialogue pipeline for procedural NPCs | 1 report | filed |
| 05 | 05-save-reload-sync-protocol.md | Save/reload timeline consistency — protocol design | 1 report (batch 2) | filed |
| 06 | 06-save-reload-timeline-sync.md | Save/reload timeline consistency — DAG model and wire protocol | 1 report (batch 2) | filed |
| 07 | 07-skyrimnet-substrate.md | SkyrimNet ecosystem due-diligence — resolves ADR-0003 | 1 report (batch 3) | filed |
| 08 | 08-social-sim-literature-v2.md | Social simulation literature v2 — implementable specification | 1 report (batch 3) | filed |
| 09 | 09-save-sync-forensics.md | Save/reload sync — third independent pass, repository forensics | 1 report (batch 4) | filed — supersedes 05/06 on specifics |
| 10 | 10-skyrimnet-health.md | SkyrimNet health deep-dive — inverts ADR-0003's provider priority | 1 report (batch 5) | filed — amends ADR-0003 |
| 11 | 11-version-pin-and-transport.md | Game version pin + HTTP/WebSocket bridge survey — resolves ADR-0008 | 3 reports (batch 6, merged) | filed — new ADR-0008 |
| 12 | 12-whiterun-dashboard-map-data.md | Whiterun debug-dashboard map assets, coordinates, telemetry, licensing | 3 reports (batch 7, merged) + 1 session pass | filed — license claims verified directly |
| 13 | 13-dashboard-prior-art-source-read.md | Dashboard prior art at source level — WS protocol, replay schema, projection | 1 source-reading pass (batch 8) | filed — resolves report 12's SkyrimWebSocket uncertainty |
| 14 | 14-isometric-render-foundations.md | 2.5D/isometric render foundations — real Whiterun geometry without building a renderer | 1 session pass (batch 8) + hands-on smoke test | filed — fo76utils verified on this machine 2026-08-22 |
| 15 | 15-skyrim-social-reactivity-mods.md | Skyrim reactive-NPC / social-consequence mod prior art — reputation, life-sim, rumor-propagation mods and their engine walls | 2 independent reports (batch 9, merged) | filed |
| 16 | 16-skyrim-economy-mods.md | Skyrim economy-simulation mod prior art — pricing/merchant mods, vendor-gold/barter engine limits | 2 independent reports (batch 9, merged) | filed — economic sim itself remains deferred to v0.4 |
| 17 | 17-skyrim-social-reactivity-mods-v2.md | Skyrim social-reactivity mod prior art — third independent pass (IntelEngine gossip chains, Town Criers, NPC Reactions' per-NPC memory timer) | 1 report (batch 10) | filed — see 15 for the merged first two passes |
| 18 | 18-skyrim-economy-mods-v2.md | Skyrim economy mod prior art — third independent pass (quantified wishlist demand, Stock Market of Skyrim, Conquest of Skyrim, Master Trader's gold-injection trick) | 1 report (batch 10) | filed — see 16 for the merged first two passes; economic sim itself remains deferred to v0.4 |
| 19 | 19-skyrim-quest-injection-machinery.md | Skyrim Radiant Story internals, IntelEngine's dynamic-quest pipeline, Story-Manager-bypass faction sims (Open Civil War vs. Organic Factions), and SKSE journal/UI injection mechanisms | 1 report (batch 11) | filed — ahead-of-need for the deferred "prospective drama management" layer; companion to comparative-systems/ai-directors-and-drama-management.md |
| 20 | 20-skyrim-quest-injection-machinery-v2.md | Skyrim quest/GM-injection machinery — second independent pass (exact Story Manager event codes, alias-storage token limits, deeper IntelEngine profile, Faction Warfare/Civil War Overhaul fragility) | 1 report (batch 12) | filed — see 19 for the first pass; companion to comparative-systems/ai-directors-and-drama-management-v2.md |
| 21 | 21-skyrim-quest-injection-machinery-v3.md | Skyrim quest/GM-injection machinery — third independent pass (Undaunted precedent, exact alias-fill-type enumeration, deep IntelEngine version history, Fred Zeleny's legibility postmortem) | 1 report (batch 13) | filed — see 19/20 for prior passes; companion to comparative-systems/ai-directors-and-drama-management-v3.md |
| — | comparative-systems/ai-directors-and-drama-management-v4.md | Drama-management/GM-agent literature — fourth independent pass, no Skyrim-specific companion this batch (Friends & Fables/ACE-1's belief-provenance-like redesign, Todd Howard's own Radiant Story design-intent quote, two new trust-failure modes) | 1 report (batch 14) | filed |
| 22 | 22-native-skse-plugin-prior-art.md + pass 2 | Native SKSE C++ plugin architecture for Chronicle's v0.2 game seam ("ChronicleBridge") — event sinks, IXWebSocket transport, threading discipline, Proton reachability risk, actor-spatial enumeration | 2 independent reports (batch 15, merged) | filed — resolves the notes/ideas.md v0.2 bridge-dependency action item; not ahead-of-need, targets the next build milestone directly. Verdict (both passes): first-party build, no SkyrimWebSocket install |
| 23 | 23-v03-hysteresis-and-action-verbs.md | v0.3 gap survey: two-way hysteresis for Grudge/Relationship state (control-theory Schmitt-trigger pattern, RimWorld mental-break ladder, absence of purpose-built literature elsewhere) and an NPC action-verb inventory beyond rule 18's avoidance (dialogue-gating on GetRelationshipRank, vendor refusal/price, AI-package globals, SkyrimNet's AttackTarget/Action Repository) | 1 web-research pass (batch 16) | filed — ahead-of-need for docs/design/next-phases-2026-08.md §2's two flagged-but-unscoped v0.3 gaps; no ADR change |
| 24 | 24-programmatic-esp-authoring.md | Verifies/refutes docs/design/chronicle-bridge-avoidance-out.md §2b's unresearched "needs the Creation Kit GUI" assumption — finds Mutagen (C#/.NET, headless) can create new PACK/CTDA records outright, xEdit scripting is a weaker fallback, the CK has no headless content-authoring mode, and RE::Actor::PutCreatedPackage offers a partial runtime-override path | 1 web-research pass (batch 17) | filed — decisive recommendation: use Mutagen headlessly; the CK-GUI-required half of the assumption was correct but non-exclusive |
| 25 | 25-devbench-skse-mcp-verification.md | Verifies a secondhand claim about alandtse/devbench, an SKSE plugin running an in-process MCP+REST test bench on 127.0.0.1:8920 — confirms the repo, Nexus listing (mod 181326), and nearly all technical claims (console-command capture, main-thread marshalling, menu/save/inspect tools, C-ABI for other plugins) are real; refutes the "MIT-licensed" claim (core is GPL-3.0, only the integration glue is MIT); assesses it could automate most of docs/design/chronicle-bridge-verification-runbook.md's manual steps once a live game session exists | 1 direct-verification pass (GitHub/Nexus primary sources) | filed — no ADR change; informs future ChronicleBridge in-game test tooling |
| 26 | 26-vendor-price-markup-hook.md | ChronicleBridge C++ mechanism for grudge-driven vendor price markup at barter-menu-open — direct header verification against a local CommonLibSSE-NG checkout | 1 header-verification pass (batch 18) | filed — RE::BarterMenu/RE::MenuOpenCloseEvent give risk-free vendor detection; the actual price write needs a reverse-engineered native price-calc hook (mod 144874's pattern), the first ChronicleBridge slice needing that risk category — scoped as its own future spike, not bundled with hydration/avoidance-tier next steps |
| 27 | 27-minimal-chronicle-dev-modlist.md | A concrete, from-scratch, minimal MO2 mod list for Chronicle/ChronicleBridge dev+debug (distinct from the owner's NGVO and Apostasy/Tuxborn personal lists) — 1.6.1170 downgrade tooling status, Address Library/USSEP/DevBench/CrashLoggerSSE/SkyUI selection, build order | 1 research pass (batch 19) | filed — revises this task's own premise: 2 of IdentityMap.cpp's 19 named-cast entries currently resolve against USSEP-attributed FormIDs, not just Skyrim.esm/HearthFires.esm; source-level read of TESForm::GetFile() shows this is load-order-dependent rather than settled record ownership, so the list keeps USSEP active to match the table's verified environment. Update (2026-08-27): the mechanism is now settled empirically, not just flagged — a live-capture cross-check confirmed TESForm::GetFile(0) returns whichever plugin currently wins the override chain for a record, not its static originating master; see IdentityMap.cpp's 2026-08-27 note and commit 78dd0ec |
| 28 | 28-vendor-price-hook-address-library-spike.md | Address Library spike for report 26's vendor-price-markup hook — reads mod 144874's actual open-source implementation (JerryYOJ/DynamicPrices-SKSE, found via GitHub code search) directly | 1 source-reading pass (batch 20) | filed — corrects report 26: no unmapped internal price-calc function exists to find; the real technique is a vtable-slot swap on the already-Address-Library-backed RE::VTABLE_BarterMenu (documented IMenu::PostCreate, vfunc 0x2) plus a Scaleform/GFx UpdateItemCardInfo callback swap, both fully inside this project's already-vendored CommonLibSSE-NG surface — downgrades the write from [RISK — reverse-engineered hook required] to [BUILD-ON], pending one live-game caveat (does the multiplied UI value drive the real transaction gold, not just display) |
| 29 | 29-crime-witness-event-extraction.md | Verifies a secondhand AI's 7 claims about Skyrim/Oblivion crime-witness mechanics and a proposed TESCrimeEvent ChronicleBridge slice, against CommonLibSSE-NG headers, UESP, and mod primary sources | 1 header-verification pass (batch 21) | filed — no RE::TESCrimeEvent exists anywhere in CommonLibSSE-NG (sharpens report 22's own flagged gap); internal Bounty::Event/AssaultCrime::Event/MurderCrime::Event sinks exist but were never wrapped into public headers, so crime/witness extraction is [RISK — reverse-engineered hook required], the same tier as report 26/28's vendor-price work, not DeathEventSink-tier; 2 of the 7 secondhand claims were refuted (no Responsibility stat in Skyrim; Skyrim's vanilla "Reputation" is a narrow Easter egg, not the described morality system) and 2 more were mischaracterized |
| 30 | 30-crime-witness-prior-art-spike.md | Follow-up prior-art spike for report 29's crime/witness R&D-spike verdict, mirroring report 28's successful vendor-price downgrade play — reads 3 real open-source SKSE plugins directly | 1 source-reading pass (batch 22) | filed — split verdict, not a clean downgrade: bounty/infamy VALUE per faction (PlayerCharacter::GetCrimeValue().crimeGoldMap) is fully routine-buildable (pollable, non-virtual, already used in a real shipped plugin); the witness SET's read mechanics are hook-free but the reference plugin manually attaches its own ExtraPlayerCrimeList bookkeeping rather than reading a vanilla-populated one, leaving open whether polling the player's own list yields report 29's assumed data (a one-session live-game check, not a full spike); event-level "a crime just happened" fidelity stays genuinely R&D-spike-tier, confirmed by a real plugin's raw trampoline detours onto unnamed internal functions found via its author's own IDA work — though Actor::ModCrimeGoldValue turns out to be a named vtable slot (0xB6), cheaper (vtable-swap tier) than report 29 implied |
| 31 | 31-diegetic-evidence-object-placement-spike.md | Can ChronicleBridge place/move a physical object in the world at runtime for a "diegetic evidence" slice (from docs/design/kimi-architecture-delta-audit.md's one genuinely-new idea) — verifies both pre-place-and-toggle and spawn-at-runtime against real CommonLibSSE-NG source and two real shipped SKSE plugins | 1 source-reading pass (batch 23) | filed — [BUILD-ON] for both engine mechanisms, no reverse-engineering needed: TESObjectREFR::Enable()/Disable() and PlaceObjectAtMe()/TESDataHandler::CreateReferenceAtLocation() are all plain RELOCATION_ID/vtable-backed calls, confirmed a second time by reading Styyx1/SurpriseSpawner and HarperZ9/skyrimbridge's real source; Mutagen's own schema (PlacedObject/Placement/InitiallyDisabled) independently supports pre-place-and-toggle's authoring side. The real gap this pass found is data, not mechanism: neither IdentityMap.cpp nor chronicle/claims.py's Evidence record (whose real field is strength, not the audit doc's evidentiary_strength) carries any location concept to bind evidence to — recommends spawn-at-runtime at an NPC's own live position as the cheaper first cut, and flags pre-place-and-toggle as blocked on a location-modeling decision, not an engine risk |
| 32 | 32-npc-home-location-data-spike.md | Closes report 31's F5 gap: what real NPC home/workplace location data does Skyrim already have, and how cheaply can Chronicle/ChronicleBridge get at it — verifies RE::TESPackage::packLoc/PackageLocation against real headers and directly dumps Ysolda's/Amren's/Braith's real Package records from the real Skyrim.esm/HearthFires.esm data via a from-scratch Mutagen program | 1 source-and-real-data-reading pass (batch 24) | filed — real static home data exists and is [BUILD-ON]-tier where a plain LocationCell home package exists (proven for Amren/Braith, both resolving to the real WhiterunAmrensHouse cell), but coverage is uneven (Ysolda has no explicit home package, only a LocationFallback/"editor location" indirection this pass could not fully resolve against the pinned Mutagen 23.4.0 schema); recommends NOT building a home-location model now — EvidencePoller.cpp's already-shipped live-position proxy covers all 19 named-cast NPCs uniformly and no roadmap item needs scene-independent location data yet |
| 33 | 33-evidence-preplace-toggle-snapshot-coordinates.md | Re-examines pre-place-and-toggle from a different angle than report 32: could adapters/skyrim/listener/whiterun-positions.json's already-captured live X/Y snapshot (from SpatialStreamer.cpp telemetry, not the AI-package system) drive it instead, sidestepping report 32's reverse-index dead end — and does Enable()/Disable() genuinely avoid the save growth PlaceObjectAtMe's a_forcePersist=true compounds, verified against real engine headers and Bethesda's save-format convention | 1 source-and-web-reading pass (batch 25) | filed — finds full 19/19 named-cast coverage (strictly better than report 32's 2/3) and confirms the save-growth/retraction benefit is real (bounded single-ChangeForm-slot toggle vs. PlaceObjectAtMe's permanent new 0xFF-prefixed "created form" entry per call), but still recommends NOT building now: the snapshot has no Z coordinate (confirmed dropped in SpatialStreamer.cpp, not an engine limitation), needs a new exterior-cell FormKey resolution step (solvable via this project's own existing floor(coord/4096) map math, not a repeat of report 32's dead end), and is diegetically staler than either the live approach or report 32's rejected home-cell idea since NPCs move on real AI-package schedules; the verified save-growth benefit is real but unmeasured against Chronicle's actual event volume, so the certain new costs aren't worth paying yet — revisit if a real playtest shows the shipped mechanism's save growth becoming an actual problem |
Source PDFs worth keeping locally (not re-reads, schema/rule-authoring
references): see papers/README.md.
Merged [BUILD-ON] list¶
- Belief data model: James Ryan et al.'s Talk of the Town facet model (Value/Predecessor/Evidence/Strength/Accuracy) — near-direct template for
chronicle's belief dataclass, already Python. (02) - Rumor propagation: Daley–Kendall SIR spread (who hears it) + Bartlett/Griffiths serial-reproduction mutation (how it changes), both O(edges) per tick. (02)
- Memory decay: ACT-R base-level activation (closed-form log-decay) + Generative Agents recency×importance×relevance score — cheap, LLM-free. (02)
- Tier interface: LLM text → numeric scalar (opinion/stance) → symbolic update, per HiSim/RumorSphere — symbolic state stays authoritative, LLM output is an annotated view, not a source of truth. (03)
- Write-back mechanism: constrained JSON decoding (XGrammar/Outlines/Guidance) is now near-zero-overhead and the field's dominant pattern; still needs a downstream semantic validator since format-valid ≠ content-valid. (03)
- Local LLM tier: 1B–8B models (Qwen3/2.5, Llama-3.x, Mantella-Skyrim-Llama-3-8B fine-tune) at Q4_K_M are practical alongside Skyrim on consumer GPUs — concrete VRAM/tok-s numbers converge across all 3 hybrid-architecture reports. (03)
- Voice design: Qwen3-TTS-VD (1.7B/0.6B, Apache 2.0) for one-time description-driven voice design; Chatterbox-Turbo (350M, MIT) as the runtime cloning engine (~75ms TTFB, <1GB VRAM, native inline tags + exaggeration slider). Adopt "design-once-then-clone": design at NPC creation, cache reference WAV by form ID, clone per line. (04)
- Event transport: never route high-frequency events through Papyrus (script-queue lag) — a CommonLibSSE-NG SKSE plugin hooking native dispatchers, forwarding via HTTP/WebSocket, is the pattern both substrate reports converge on. (01)
- NPC data ingestion: Mutagen or the xEdit Info NPC Extractor script, plus UESP CC-BY-SA bios. (01)
- Save/reload identity: embed a
SaveUUID+ParentSaveUUID+ monotonicgeneration/SaveSequencein the SKSE co-save (TMNLrecord) — strictly stronger than any existing mod's approach (CHIM's clock-onlygamets, Mantella's none, SkyrimNet's in-process-only). See ADR-0004. (05, 06) - Timeline model: model Skyrim's save topology as a DAG of branches keyed by
(save_uuid, generation); fork on reload, never roll back; derive state by path traversal from root to head. See ADR-0004 and thechronicle/events.pybranch-key change. (05, 06) - Sync handshake: gate writes on an explicit watermark/epoch handoff between the SKSE shim and the service, not on
kPostLoadGamealone; buffer/suppress events during the load window. See ADR-0005. (05, 06, independently re-derived by 07, and superseded on specifics by 09's HELLO/RESOLVE/ACK protocol with a six-way decision table and a DEGRADED mode for service-down-at-load) - Save-sync forensics: report 09 goes past architecture into repository forensics (specific CHIM PRs #560/#572/#558/#681, SkyrimNet issues #251/#487/#119/#391) and resolves the SkyrimNet-reload-behavior conflict left open after 05/06: SkyrimNet asks the player before clearing (
ClearTimelineMessage/msgClearHistory), confirmed via issue #251 — it neither silently ignores (05's read) nor runs a fully automatic cleanup (06's read). Agrees with 05/06/07 on architecture (event-sourced, fork-not-rollback, save-embedded UUID); upgrades ADR-0004/0005 on specifics (bitemporal columns, reachability-based GC, the manifest schema, the handshake decision table). (09) - Substrate Abstraction Layer: a generic Python provider interface in
chronicle/, both implemented underadapters/. Resolves ADR-0003 (07); provider priority inverted by report 10 — the PO3-Extender+SKSE_HTTP standalone path is the reference implementation built first, SkyrimNet is an optional adapter pinned to one beta/API version with a startup handshake. See ADR-0003's amendment. - Five-layer data ownership: canonical events → claims/variants → subjective beliefs → social state → narrative/query. Only the first layer is objective. See ADR-0006. (08)
- Sparse-graph rule: never maintain a complete N×N social matrix — sparse acquaintance/witness/family/faction edges only, evidenced by Socialog's 15-25ms→600ms per-tick cost growth from 50→450 characters. See ADR-0006. (08)
- Observer-local reputation: Beta-distribution
(alpha, beta)per(observer, subject, context), never one global score. See ADR-0006. (08) - Inspectability: every derived social outcome must answer "who believes this, from what evidence, through whom, since when." See ADR-0007. (08)
- Dashboard map backdrop: no permissively-licensed Whiterun map exists; generate the backdrop yourself (CK
Create Local MapsoverWhiterunWorld, or esm-geometry parsing at install time) and treat the generator as the distributable artifact, never the rendered image. Whiterun is its own worldspace (0x0001A26F) with interior cells on local coordinates — the map tool needs per-cell layers. (12) - Dashboard frontend prior art: uesp-gamemap code is MIT (tile pyramid + marker layer); Stanford's generative_agents is Apache-2.0 and its successor StanfordHCI/genagents is MIT (both verified 2026-08-22) — contributing time-scrubbed replay, the key pattern for rumor/belief debugging. Coordinate extraction: skyrim-cell-dump (MIT — Cargo.toml declaration, verified) + Mutagen or a short xEdit script; NPC schedule targets need PACK records. WhiterunWorld FormID
0x0001A26F; cell mathfloor(gameX/4096), two-point affine calibration is exact for Skyrim's linear projection. (12) - Live telemetry channel: in-process SKSE plugin hosting a local WebSocket (SkyrimWebSocket — MIT verified, CommonLibSSE-NG multi-runtime, 1.6.1170-compatible, active 2026-08) is the adopted reference; its wire protocol and spatial JSON block are Chronicle's canonical transport/ActorLocation schema (13). Fork plan for the bulk-actor stream (
RE::ProcessListsresolver) has exact hook points. Reject external memory-reading. (12, 13) - Sim trace/replay format: adopt Smallville's step-file schema + delta compression (only-changed agents per step) for the headless JSONL trace; dashboard adds the scrubber Smallville lacks. One frontend, two feeds (headless sim now, SkyrimWebSocket later). (13)
- Isometric/2.5D backdrop: renderable from real game geometry without a from-scratch renderer — fo76utils (MIT, pending TES5-statics verification) or ByroRedux (MIT, verified rendering WhiterunWorld, heavier); both read the user's own game files so no Bethesda assets ship. The downloaded 1.6.1170 depot files serve as the render corpus without touching the live install. (14)
Merged [RISK] list¶
- SkyrimNet build-vs-study disagreement — see Open Questions below; this is the sharpest unresolved item and bears directly on ADR-0003. (01)
- VRAM contention: Skyrim (6–9GB) + local LLM (3.5–5GB) + TTS must coexist on a single 10–16GB consumer GPU — forces the voice tier to sub-1GB models (Chatterbox-Turbo/Nano); larger/expressive TTS models must be one-time/offline use only. (04)
- Licensing/personality-rights: Coqui XTTS v2 (Mantella's current TTS) is CPML non-commercial-only; Nexus Mods bans non-consensual real-voice-actor clones. Fully synthetic description-driven voices (Qwen3-TTS-VD) are the only legally defensible path for a distributed free mod. (04)
- Sparse vanilla relationship data: only ~586 relationships across 397 NPCs found in one RELA audit — most of Chronicle's social graph must be synthesized, not extracted. (01)
- Engine-update fragility: SKSE plugins (including any custom bridge) break on Bethesda engine updates (one flagged Aug 14 2026) — keep the Python/simulation side fully decoupled from the thin in-game bridge so an update only breaks the adapter, not the sim. (01)
- "More LLM agents degrades fidelity" is real but nuanced — it's a cost/diversity/calibration effect, not a hard population ceiling; scaling total population is fine, scaling the LLM-driven share of it is what hurts. (03)
- Persona drift, formality collapse, memory fabrication are documented and quantified in long-running LLM agents (Multi-IF, Laban et al., Lifelong-SOTOPIA, GATSim); mitigated by provenance-typed writes and per-turn persona re-injection, not by longer context windows. (03)
- Evaluation is the field's acknowledged bottleneck, not model capability — plan for regression scenarios against designer-defined curves plus held-out human rating from day one; never validate with an LLM judge that was also used to generate the content being judged. (03)
- City of Gangsters' >20-rule ceiling, CK3's throttle from ~300 to ~30 AI interactions per character per century post-launch — legibility and a per-tick interaction budget cap matter more than model sophistication at ~1,000-NPC scale. (02)
- No prior Skyrim reputation/rumor mod actually implements propagation — confirms this is a genuine gap, not reinvention, but also means there's no prior art to lean on for the game-side UX of surfacing rumors to the player. Closest exception found: SkyrimNet's community plugin IntelEngine ships "gossip chains that propagate between NPCs" — the first shipped NPC-to-NPC propagation found across four independent reports — but the payload stays textual/LLM-generated and does not re-drive AI packages or disposition. (01, 15, 17)
- An external-process architecture bypasses Papyrus compute and save-bloat, but not the write-back walls — results still have to enter the game through the same narrow engine hooks everyone else uses (barter price calc, vendor gold, dialogue conditions, leveled-list injection), and those hooks carry their own hard limits (the 32,767 signed-16-bit vendor-gold cap; the
fBarterBuyMinprice floor; merchant chests only populating on barter-menu open). The open engineering question is sharpened by report 18 into two specific, named, unattempted problems: continuous event exfiltration from the engine at scale, and NPC-merchant persistent state independent of the chest-respawn timer. (15, 16, 18) - The 2025–2026 native-SKSE-hook pricing generation (Dynamic Pricing/Prices Frameworks, The Gilded Road) is a strong reception signal for Chronicle's own architecture bet: The Gilded Road's 1,049-upvote release thread is the most enthusiastically received economy mod in the surveyed record, and it's explicitly "no scripts, no dirty edits, no save bloat" — direct community validation that external-computation-plus-thin-engine-footprint is what players reward, not just what avoids engine walls. (18)
- No in-engine mod can simulate off-screen NPC life at all — this is an absence-of-execution wall, not a performance wall. AI/scripts simply do not run for unloaded actors, and loaded actors have a documented one-hour position-update bug on top (
NPC AI Process Position Fix - NG). Chronicle's external process bypasses an absence, not just a slowdown. (17) - Dynamic quest generation is bounded to combinatorial alias-matching over pre-authored templates — the engine cannot synthesize new quest logic at runtime under any architecture, since
TESQuestforms must be compiled into a plugin before runtime and no SKSE plugin can construct arbitrary serialized quest forms in memory without corruption risk. Any future GM/director layer's "generation" has to mean template selection + alias binding, never new logic. (19) - A GM/director layer, if ever built, converges independently on the same four-stage pipeline from both the Skyrim-specific angle and the cross-game academic-literature angle: input (simulation state) → recognition/sifting (find dramatically interesting configurations) → intervention (map to an available engine verb) → presentation (surface via journal/dialogue/spawns). Provenance-anchored intervention — generating content from already-tracked simulation state rather than decorating an independently-rolled event — is the load-bearing idea across both reports and the closest thing to a validated design principle for this deferred layer. (19, 20, comparative-systems/ai-directors-and-drama-management.md, comparative-systems/ai-directors-and-drama-management-v2.md)
- Invest in intervention vocabulary before selection intelligence — the single sharpest lesson from the academic drama-management failure record. Search-based drama management failed to transfer from Deadline to Anchorhead not because the optimizer was weak but because the authored DM actions were too weak to move story quality; a synthetic "maximally powerful" action set fixed it even with a weaker algorithm. Any future Chronicle GM should prioritize a rich, provenance-carrying action vocabulary over a clever picker. (comparative-systems/ai-directors-and-drama-management-v2.md)
- No API exists to write arbitrary free text into Skyrim's native quest journal — only pre-authored, token-slotted templates.
SetObjectiveDisplayedtoggles a pre-authored objective by index; the only text-injection mechanism is<Alias=...>/stores-text token replacement, capped at 259 characters per paragraph via the community's Dynamic Book Entries workaround. Any GM-generated journal content must be authored as short, token-slotted template text, never generated prose. (20) - A former Bethesda designer's own postmortem is the sharpest primary-source confirmation yet that legibility, not generation quality, is the core risk of any hidden simulation: "the deep Radiant AI reactions happened off-screen and the player never noticed them… we were doing a lot of work that the players wouldn't or even couldn't appreciate" (Fred Zeleny). This upgrades Chronicle's inspectability requirement (
docs/decisions/0007-inspectability.md) from a debugging/trust nicety to the specific fix for the failure mode that sank Bethesda's own original ambitions for this exact system. (21) - Hard 2024–2026 benchmark evidence that unconstrained LLM narration drifts badly, and three named systems that don't: NCP-Bench reports 40–68% fact-conflict rates and <14% narrative-commitment satisfaction for pure LLM narrators; TSL-automata neuro-symbolic control reaches ≥96% adherence vs. 14.67% for pure LLM; function-calling into a constraint-enforcing back-end never produced an invalid output. Slice of Life (deterministic symbolic sim + LLM restricted to surface text only, no feedback into simulation state) is the closest published analog to Chronicle's own committed architecture. (comparative-systems/ai-directors-and-drama-management-v3.md)
- Perceived fairness is not the same as statistical fairness (Sid Meier's Civilization rubber-banding history) — a well-calibrated reprisal can still read as unfair if it violates player expectation, a distinct failure mode from "invisible decisive variables" that needs its own tuning pass, not just legibility. (comparative-systems/ai-directors-and-drama-management-v3.md)
- A commercial AI-GM product (Friends & Fables' ACE-1) independently converged on Chronicle's belief-provenance model under production pain: after its v1 suffered LLM state-drift ("a creature narrated both dead and alive"), its redesign separated the GM (face) from a campaign engine (truth) storing atomic, provenance-carrying memory facts, plus a "View Context" transparency feature — "when an LLM lacks a source of truth, it's more prone to making things up." If Chronicle ever surfaces GM-generated content to players, an equivalent context-inspector is the concrete, shipped-precedent way to earn trust. (comparative-systems/ai-directors-and-drama-management-v4.md)
- Deep simulation the presentation layer can't surface is wasted depth — Wildermyth's own team built and discarded a more simulationist overland map for exactly this reason. Since Chronicle's architecture bets heavily on a rich, sparse social-simulation graph, this is a direct caution: concentrate depth where the presentation layer can actually show it, not just where the simulation can compute it. (comparative-systems/ai-directors-and-drama-management-v4.md)
- No existing mod solves save/reload consistency cleanly — Mantella ignores it (drift), CHIM prunes globally by clock comparison (not per-slot), SkyrimNet's reload story is disputed between the two batch-2 reports (in-process/no fork vs. an explicit but unverified cleanup protocol). This is now addressed by ADR-0004/0005, but remains one of the least-precedented parts of the design — expect to implement and test from scratch. (05, 06)
- FormID instability: a stored 32-bit FormID becomes invalid if the player's load order changes (mod add/remove/reorder shifts the ModIndex bits). Chronicle must never persist raw FormIDs. (06)
- SkyrimNet direct coupling rated HIGH RISK as a sole dependency: closed C++ core, no LICENSE file, single Ko-fi-funded maintainer, in-process design means a core exception is a crash-to-desktop. Mitigated, not eliminated, by the SAL (07).
- API version drift, with concrete integrator damage: v6→v9 in ~1 month (Beta18→Beta20); Beta21 shipped explicit breaking changes; IntelEngine hard-gated on a specific version and once blocked on an unreleased build; SeverActions hit an init-ordering deadlock and a schema break. This concrete evidence is what moved SkyrimNet from "primary provider, hedged" (07) to "optional adapter, pinned" (10) — see ADR-0003's amendment. (07, sharpened by 10)
- No LICENSE/continuity statement, now confirmed via exhaustive-as-possible targeted search (not just "not found in passing") across GitHub, docs, FAQ, Patreon, Ko-fi, Reddit. Action item tracked in
notes/ideas.md: ask the maintainer directly. (10) - Dashboard asset licensing traps: every ready-made Whiterun map asset is non-redistributable (Prima-guide-derived GameMapScout map; CC BY-NC-ND DeviantArt maps; proprietary MapGenie; Bethesda-derived UESP/CK renders); modmapper/esper/SkyrimNet-GamePlugin are source-available with no LICENSE — internal use OK, no vendoring. Bulk-downloading Nexus mods violates Nexus ToS. (12)
Open questions raised¶
See docs/decisions/open-questions.md:
- Resolved by direct repo verification: MinAI is deprecated (confirmed), Mantella's latest release is v0.14 published 2026-04-21 (confirmed), CHIM/HerikaServer is MIT-licensed (confirmed). Report 01 has been corrected in place.
- Closed by research: save/reload timeline consistency — reports 05 and 06 answered the drafted prompt. ADR-0004 (timeline branching) and ADR-0005 (sync handshake) are now drafted from their recommendations, and
chronicle/events.pycarries a branch key. Two implementation-risk uncertainties carried forward (not fully resolved): CHIM's exact fork trigger is reconstructed, not confirmed; the save-embedded-UUID pattern has no confirmed Skyrim precedent. A third disagreement surfaced between reports 05 and 06 on how SkyrimNet itself handles reloads (implicit/none vs. an explicit but unverified cleanup protocol) — logged, not resolved, since Chronicle doesn't depend on SkyrimNet's own reload behavior for its own protocol either way. - Closed by research: SkyrimNet build-vs-study — report 07 resolves ADR-0003 with a Substrate Abstraction Layer, rating direct SkyrimNet coupling HIGH RISK and the SAL hedge MEDIUM RISK. ADR-0003 is now
accepted. - Researched and deferred, not forgotten: economic simulation (prices, supply, trade ripple) — report 16 surveys the mod prior art and engine write-back limits ahead of need, but the tier itself stays out of scope until the belief tier is proven, slated v0.4.
- Closed by research (batch 6, out of cycle): game version pin — three independent reports, fired in response to the 1.7.99 patch breaking the plugin ecosystem on 2026-08-20, unanimously recommend pinning to 1.6.1170 + SKSE 2.2.6. Resolved as ADR-0008. This was flagged as a real gap in
notes/ideas.mdbefore any report addressed it. - Closed by research (batch 7, dashboard): Whiterun map assets / licensing for the debug dashboard — report 12 answers "can we build and distribute a 2D Whiterun map tool" (yes: generate the backdrop, ship the generator, reuse MIT/Apache prior art, in-process SKSE WebSocket for live telemetry). Feeds the dashboard slice, not an ADR — no decision-record change needed.
Research phase: complete (pre-build); build-phase reports continue¶
11 reports across 6 batches covered the pre-build questions (batch 6 arrived after v0.1 was
already accepted and build had started — the 1.7.99 patch forced an
out-of-cycle research pass). Build-phase research continues as needed:
batch 7 (report 12, dashboard map assets/licensing, 3 reports merged)
arrived during the v0.1 build; batch 8 (reports 13/14, dashboard
source-level prior art and isometric-render foundations), batch 9
(reports 15/16, Skyrim social-reactivity and economy mod prior art), and
batch 10 (reports 17/18, third independent passes on the same two batch-9
topics) followed the same pattern — ahead-of-need surveys filed for later
milestones (the dashboard and the v0.4 economy tier respectively), not
blocking current build work. Every ADR the pre-build research surfaced a need for
has been drafted: 0001/0002 (accepted at scaffold time), 0003 (substrate,
amended once), 0004/0005 (timeline branching / sync handshake —
independently confirmed four times over), 0006 (data ownership layers),
0007 (inspectability), 0008 (game version pin). The project is in build:
chronicle/claims.py (layer 2/3 claim/variant/belief store) is the first
code milestone, per docs/v0.1-spec.md.