docs(diagrams): add decision diagrams across all domains

16 d2 diagrams covering architecture (IPC bridge, system tiers,
testability, audio bus), data flow (perception, dialogue, eavesdrop
pipelines), entity (knowledge graph, NPC generation, dialogue tags),
state (simulation tiers, movement stances, knowledge confidence), and
UI (HUD layout, interaction flow, fog layers). PNG output for universal
viewer compatibility. Removes test SVG from font debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-23 11:57:07 +01:00
co-authored by Claude Opus 4.6
parent 08dfadb863
commit 1e556ccca2
33 changed files with 2153 additions and 97 deletions
+121
View File
@@ -0,0 +1,121 @@
# Audio Architecture — D-068, D-073
# 5-bus audio system with zone crossfade and AudioManager singleton.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
direction: down
server_event: Rust Server\n(ObserverSnapshot) {
shape: hexagon
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
zone_id: zone_id per tile {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
sound_events: sound events {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
manager: AudioManager\n(GDScript autoload singleton) {
shape: hexagon
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
registry: Directory-scan registry\n(res://audio/ on startup) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
crossfade: Zone crossfade\n1.5-2s tween on zone_id change {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
}
buses: 5-Bus Mixer {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
music: Bus 1 — Music\n(reserved · empty v0.1) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 5
}
ambient: Bus 2 — Ambient\n(station hum + zone overlays) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
world_sfx: Bus 3 — World SFX\n(NPC footsteps · doors · env events) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
player_actions: Bus 4 — Player Actions\n(footsteps · future: combat · items) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
ui_sounds: Bus 5 — UI Sounds\n(cursor hover · implant open · chimes) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
sliders: Player Volume Sliders\n(1 per bus · in Settings) {
shape: queue
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
dips: Audio Dip Profiles (D-069) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
dialogue_dip: Dialogue\nAmbient -6 to -8dB · 300ms in {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
confrontation_dip: Confrontation\nAmbient -10 to -12dB + LPF · 500ms in {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
listen_boost: ListeningFocus\nWorld SFX +2 to +3dB\n(stationary 30+ ticks) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
server_event.zone_id -> manager.crossfade: "zone change" { style.stroke: ${color-accent} }
server_event.sound_events -> manager: "typed events" { style.stroke: ${color-stroke} }
manager.registry -> manager.crossfade: "filename → AudioStream" { style.stroke: ${color-stroke} }
manager -> buses.ambient: "loop" { style.stroke: ${color-accent} }
manager -> buses.world_sfx: "event" { style.stroke: ${color-stroke} }
manager -> buses.player_actions: "event" { style.stroke: ${color-stroke} }
manager -> buses.ui_sounds: "event" { style.stroke: ${color-stroke} }
sliders -> buses: "proportional volume" { style.stroke: ${color-stroke} }
dips -> buses.ambient: "proportional dip" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
dips -> buses.world_sfx: "proportional dip" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
Binary file not shown.

After

Width:  |  Height:  |  Size: 568 KiB

+146
View File
@@ -0,0 +1,146 @@
# IPC Bridge Architecture — D-020
# Godot client + Rust simulation server via subprocess/IPC
# Single-player: subprocess + local socket. Multiplayer: TCP (same protocol).
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
direction: right
godot: Godot Client {
shape: hexagon
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
renderer: Renderer {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
}
ui: UI + HUD {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
}
audio: AudioManager {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
}
input: Input Capture {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
}
bridge_client: SimBridge (LocalBridge / NetworkBridge) {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-accent}
}
}
transport: Transport Layer {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
sp: Single-player\nUnix socket / localhost TCP {
style.fill: ${color-bg}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
mp: Multiplayer\nRemote TCP {
style.fill: ${color-bg}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
}
rust: Rust Simulation Server {
shape: hexagon
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
bridge_server: SimBridge (recv end) {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-accent}
}
ecs: bevy_ecs World {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
}
perception: Perception System {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
}
ai: AI + Storyteller {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
}
kg: Knowledge Graph {
style.fill: ${color-dim}
style.font-color: ${color-text}
style.stroke: ${color-stroke}
}
}
msgpack_out: PlayerInput (MessagePack) {
shape: queue
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
msgpack_in: ObserverSnapshot (MessagePack) {
shape: queue
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
godot.input -> msgpack_out: "semantic actions\n(MoveNorth, Interact, UsePerceptionMode)" {
style.stroke: ${color-accent}
}
msgpack_out -> godot.bridge_client
godot.bridge_client -> transport.sp: "single-player" {
style.stroke: ${color-accent}
style.stroke-dash: 4
}
godot.bridge_client -> transport.mp: "multiplayer" {
style.stroke: ${color-accent}
style.stroke-dash: 4
}
transport.sp -> rust.bridge_server {
style.stroke: ${color-accent}
style.stroke-dash: 4
}
transport.mp -> rust.bridge_server {
style.stroke: ${color-accent}
style.stroke-dash: 4
}
rust.bridge_server -> rust.ecs: "dispatch input" {
style.stroke: ${color-stroke}
}
rust.ecs -> rust.perception
rust.ecs -> rust.ai
rust.ecs -> rust.kg
rust.ecs -> msgpack_in: "ObserverSnapshot\n(entities, fog, sound events,\nmonologue triggers, HUD widgets)" {
style.stroke: ${color-accent}
}
msgpack_in -> godot.bridge_client
godot.bridge_client -> godot.renderer
godot.bridge_client -> godot.ui
godot.bridge_client -> godot.audio
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

+133
View File
@@ -0,0 +1,133 @@
# Simulation Tiers + Multiplayer-Ready Principles — D-026, D-010, D-009
# Four simulation tiers with LRU eviction.
# D-010: four non-negotiable architectural principles embedded as annotations.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
direction: down
principles: Architectural Principles (D-010) {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.border-radius: 4
p1: Client-Server Separation\neven in single-player {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
p2: Information Boundaries\nas first-class system {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
p3: No Baked Player Identity\n"characters, some player-controlled" {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
p4: Deterministic Simulation\ntimestamped input events {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
tiers: Simulation Tiers (D-026) {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.border-radius: 4
active: Tier 1 — Active {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.bold: true
}
background: Tier 2 — Background {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
saved: Tier 3 — State-Saved {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
ungenerated: Tier 4 — Ungenerated {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 5
}
}
active_detail: 30-80 NPCs\nFull sim · 10-20 ticks/sec\nScope tags keep NPCs here {
shape: page
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
background_detail: 500-2,000 NPCs\nState machine · 1 tick/game-minute\n(schedule · mood · relationships · job) {
shape: page
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
saved_detail: 10,000+ NPCs\nFrozen serialized structs ~1-2KB\nReactivate on player return ~2-5ms {
shape: page
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
eviction: LRU Eviction\n(interaction-timestamp priority queue) {
shape: diamond
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
tiers.active -> active_detail {
style.stroke: ${color-accent}
}
tiers.background -> background_detail {
style.stroke: ${color-stroke}
}
tiers.saved -> saved_detail {
style.stroke: ${color-stroke}
}
tiers.active -> tiers.background: "evict (LRU)" {
style.stroke: ${color-accent}
style.stroke-dash: 4
}
tiers.background -> tiers.active: "player proximity\nor scope tag" {
style.stroke: ${color-accent}
}
tiers.background -> tiers.saved: "evict (LRU)" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
tiers.saved -> tiers.background: "player return" {
style.stroke: ${color-stroke}
}
tiers.ungenerated -> tiers.saved: "player approach\n(generated ahead of arrival)" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
eviction -> tiers {
style.stroke: ${color-accent}
style.stroke-dash: 4
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 547 KiB

@@ -1,97 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" data-d2-version="0.7.1" preserveAspectRatio="xMinYMin meet" viewBox="0 0 712 274"><svg class="d2-1525458463 d2-svg" width="712" height="274" viewBox="-101 -86 712 274"><rect x="-101.000000" y="-86.000000" width="712.000000" height="274.000000" rx="0.000000" fill="#1E1E2E" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-1525458463 .text-bold {
font-family: sans-serif; font-weight: bold;
}
.d2-1525458463 .text-italic {
font-family: sans-serif; font-style: italic;
}
]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-1525458463 .fill-N1{fill:#CDD6F4;}
.d2-1525458463 .fill-N2{fill:#BAC2DE;}
.d2-1525458463 .fill-N3{fill:#A6ADC8;}
.d2-1525458463 .fill-N4{fill:#585B70;}
.d2-1525458463 .fill-N5{fill:#45475A;}
.d2-1525458463 .fill-N6{fill:#313244;}
.d2-1525458463 .fill-N7{fill:#1E1E2E;}
.d2-1525458463 .fill-B1{fill:#CBA6f7;}
.d2-1525458463 .fill-B2{fill:#CBA6f7;}
.d2-1525458463 .fill-B3{fill:#6C7086;}
.d2-1525458463 .fill-B4{fill:#585B70;}
.d2-1525458463 .fill-B5{fill:#45475A;}
.d2-1525458463 .fill-B6{fill:#313244;}
.d2-1525458463 .fill-AA2{fill:#f38BA8;}
.d2-1525458463 .fill-AA4{fill:#45475A;}
.d2-1525458463 .fill-AA5{fill:#313244;}
.d2-1525458463 .fill-AB4{fill:#45475A;}
.d2-1525458463 .fill-AB5{fill:#313244;}
.d2-1525458463 .stroke-N1{stroke:#CDD6F4;}
.d2-1525458463 .stroke-N2{stroke:#BAC2DE;}
.d2-1525458463 .stroke-N3{stroke:#A6ADC8;}
.d2-1525458463 .stroke-N4{stroke:#585B70;}
.d2-1525458463 .stroke-N5{stroke:#45475A;}
.d2-1525458463 .stroke-N6{stroke:#313244;}
.d2-1525458463 .stroke-N7{stroke:#1E1E2E;}
.d2-1525458463 .stroke-B1{stroke:#CBA6f7;}
.d2-1525458463 .stroke-B2{stroke:#CBA6f7;}
.d2-1525458463 .stroke-B3{stroke:#6C7086;}
.d2-1525458463 .stroke-B4{stroke:#585B70;}
.d2-1525458463 .stroke-B5{stroke:#45475A;}
.d2-1525458463 .stroke-B6{stroke:#313244;}
.d2-1525458463 .stroke-AA2{stroke:#f38BA8;}
.d2-1525458463 .stroke-AA4{stroke:#45475A;}
.d2-1525458463 .stroke-AA5{stroke:#313244;}
.d2-1525458463 .stroke-AB4{stroke:#45475A;}
.d2-1525458463 .stroke-AB5{stroke:#313244;}
.d2-1525458463 .background-color-N1{background-color:#CDD6F4;}
.d2-1525458463 .background-color-N2{background-color:#BAC2DE;}
.d2-1525458463 .background-color-N3{background-color:#A6ADC8;}
.d2-1525458463 .background-color-N4{background-color:#585B70;}
.d2-1525458463 .background-color-N5{background-color:#45475A;}
.d2-1525458463 .background-color-N6{background-color:#313244;}
.d2-1525458463 .background-color-N7{background-color:#1E1E2E;}
.d2-1525458463 .background-color-B1{background-color:#CBA6f7;}
.d2-1525458463 .background-color-B2{background-color:#CBA6f7;}
.d2-1525458463 .background-color-B3{background-color:#6C7086;}
.d2-1525458463 .background-color-B4{background-color:#585B70;}
.d2-1525458463 .background-color-B5{background-color:#45475A;}
.d2-1525458463 .background-color-B6{background-color:#313244;}
.d2-1525458463 .background-color-AA2{background-color:#f38BA8;}
.d2-1525458463 .background-color-AA4{background-color:#45475A;}
.d2-1525458463 .background-color-AA5{background-color:#313244;}
.d2-1525458463 .background-color-AB4{background-color:#45475A;}
.d2-1525458463 .background-color-AB5{background-color:#313244;}
.d2-1525458463 .color-N1{color:#CDD6F4;}
.d2-1525458463 .color-N2{color:#BAC2DE;}
.d2-1525458463 .color-N3{color:#A6ADC8;}
.d2-1525458463 .color-N4{color:#585B70;}
.d2-1525458463 .color-N5{color:#45475A;}
.d2-1525458463 .color-N6{color:#313244;}
.d2-1525458463 .color-N7{color:#1E1E2E;}
.d2-1525458463 .color-B1{color:#CBA6f7;}
.d2-1525458463 .color-B2{color:#CBA6f7;}
.d2-1525458463 .color-B3{color:#6C7086;}
.d2-1525458463 .color-B4{color:#585B70;}
.d2-1525458463 .color-B5{color:#45475A;}
.d2-1525458463 .color-B6{color:#313244;}
.d2-1525458463 .color-AA2{color:#f38BA8;}
.d2-1525458463 .color-AA4{color:#45475A;}
.d2-1525458463 .color-AA5{color:#313244;}
.d2-1525458463 .color-AB4{color:#45475A;}
.d2-1525458463 .color-AB5{color:#313244;}.appendix text.text{fill:#CDD6F4}.md{--color-fg-default:#CDD6F4;--color-fg-muted:#BAC2DE;--color-fg-subtle:#A6ADC8;--color-canvas-default:#1E1E2E;--color-canvas-subtle:#313244;--color-border-default:#CBA6f7;--color-border-muted:#CBA6f7;--color-neutral-muted:#313244;--color-accent-fg:#CBA6f7;--color-accent-emphasis:#CBA6f7;--color-attention-subtle:#BAC2DE;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-B2{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-B3{fill:url(#streaks-dark-d2-1525458463);mix-blend-mode:overlay}.sketch-overlay-B4{fill:url(#streaks-dark-d2-1525458463);mix-blend-mode:overlay}.sketch-overlay-B5{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-B6{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-AA2{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-AA4{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-AA5{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-AB4{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-AB5{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-N1{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-N2{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-N3{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-dark-d2-1525458463);mix-blend-mode:overlay}.sketch-overlay-N5{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-N6{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-N7{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.light-code{display: none}.dark-code{display: block}]]></style><g class="Y2xpZW50"><g class="shape" ><path d="M 43 17 L 0 51 L 43 86 L 128 86 L 171 51 L 128 17 Z" stroke="#CBA6f7" fill="#45475A" class=" stroke-B1 fill-N5" style="stroke-width:2;" /></g><text x="85.500000" y="57.000000" fill="#CDD6F4" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Godot Client</text></g><g class="c2VydmVy"><g class="shape" ><path d="M 389 17 L 349 51 L 389 86 L 470 86 L 510 51 L 470 17 Z" stroke="#CBA6f7" fill="#45475A" class=" stroke-B1 fill-N5" style="stroke-width:2;" /></g><text x="429.500000" y="57.000000" fill="#CDD6F4" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Rust Server</text></g><g class="KGNsaWVudCAtJmd0OyBzZXJ2ZXIpWzBd"><marker id="mk-d2-1525458463-3488378134" markerWidth="10.000000" markerHeight="12.000000" refX="7.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" fill="#CBA6f7" class="connection fill-B1" stroke-width="2" /> </marker><path d="M 157.969089 38.649729 C 239.199997 24.200001 280.600006 24.200001 359.063000 38.292869" stroke="#CBA6f7" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-1525458463-3488378134)" mask="url(#d2-1525458463)" /><text x="259.500000" y="30.000000" fill="#BAC2DE" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">stdin IPC</text></g><g class="KHNlcnZlciAtJmd0OyBjbGllbnQpWzBd"><path d="M 361.031500 63.353566 C 280.600006 77.800003 239.199997 77.800003 159.938177 63.700541" stroke="#CBA6f7" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-1525458463-3488378134)" mask="url(#d2-1525458463)" /><text x="259.500000" y="83.000000" fill="#BAC2DE" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">stdout IPC</text></g><mask id="d2-1525458463" maskUnits="userSpaceOnUse" x="-101" y="-86" width="712" height="274">
<rect x="-101" y="-86" width="712" height="274" fill="white"></rect>
<rect x="228.000000" y="14.000000" width="63" height="21" fill="black"></rect>
<rect x="223.000000" y="67.000000" width="73" height="21" fill="black"></rect>
</mask></svg></svg>

Before

Width:  |  Height:  |  Size: 8.3 KiB

+126
View File
@@ -0,0 +1,126 @@
# Testability Architecture — D-030
# Three-layer IPC testing, test runner tooling, and phase priorities.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
direction: down
runners: Test Runners {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
rust_runner: cargo nextest\n(Rust) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
godot_runner: gdUnit4\n(Godot) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
wrapper: bash wrapper scripts\n(tests/ directory) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
output: Test Output {
shape: page
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
ipc_layers: IPC Test Layers {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
l1: Layer 1 — Fixture Serialization\nRoundtrip (fast · every edit) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.bold: true
}
l2: Layer 2 — Mock Subprocess Protocol\nState machine (medium · every PR) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l3: Layer 3 — Real Subprocess Integration\n(slow · daily / pre-merge) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
}
phases: Test Phases {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
ph1: Phase 1 (Sprint 1-2)\nInfra + collision / pathfinding / time {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
ph2: Phase 2 (Sprint 3-4)\nMonologue pipeline + info boundary negatives {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
ph3: Phase 3 (Sprint 5+)\nCauseChain + divergent snapshots {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
}
constraints: Production Code Constraints {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
c1: No cfg(test) in production code {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
c2: ECS World setup replaces mock injection {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
c3: CauseChain = production component\n(monologue provenance + debugging) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
c4: Deterministic replay (D-010 P4)\nSimulationTime · SimRng · InputQueue injectable {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
}
runners.rust_runner -> output: "JSON summary\n+ JUnit XML (CI)" { style.stroke: ${color-stroke} }
runners.godot_runner -> output: "JSON summary\n+ JUnit XML (CI)" { style.stroke: ${color-stroke} }
runners.wrapper -> runners.rust_runner
runners.wrapper -> runners.godot_runner
ipc_layers.l1 -> ipc_layers.l2: "gates" { style.stroke: ${color-accent} }
ipc_layers.l2 -> ipc_layers.l3: "gates" { style.stroke: ${color-accent} }
phases.ph1 -> phases.ph2: "unblocks" { style.stroke: ${color-stroke} }
phases.ph2 -> phases.ph3: "unblocks" { style.stroke: ${color-stroke} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 437 KiB

@@ -0,0 +1,171 @@
# Dialogue Pipeline — D-028, D-062, D-063, D-064, D-075
# Four relational layers, two-phase verb computation, invisible locks,
# confrontation weight, walk-away consequences.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
direction: down
player_action: Player Initiates Interaction {
shape: oval
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
verb_phase1: Phase 1 — Simulation\n(no KnowledgeGraph read) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.border-radius: 4
object_type: ObjectType component\n→ max possible verb set {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
verb_phase2: Phase 2 — Observer\n(reads KnowledgeGraph) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.border-radius: 4
kg_filter: Filter by KG confidence\n(Confront requires KnowsDetails+) {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
poi_flip: POI priority flip\n+ contradiction markers {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
archetype_filter: Archetype filter rules\n(same crate: smuggler→Stash · detective→Flag) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
layer_filter: Four Relational Layers (D-028) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
l1: Layer 1 — Access Tier\n(RelationshipState only) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l2: Layer 2 — Relationship History\n(interaction log: greeting + topic) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l3: Layer 3 — Trust-gated Gossip\n(RelationshipState AND KnowledgeConfidence — D-075) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
l4: Layer 4 — Unprompted Disclosure\n(weighted by trust + mood) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
invisible_locks: Invisible Locked Options (D-062) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.border-radius: 4
rule: Locked options = completely invisible\nNo grayed-out · no lock icons · no hints {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
reveal: New options appearing on repeat visits\n= the reward (dopamine) {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
}
confrontation: Confrontation Weight (D-063) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.border-radius: 4
voice: Written in character's internal voice\n(italicized first-person) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
monologue_beat: Pre-delivery monologue beat\n1-2s: "No taking it back." {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
world_reacts: World reacts\n(NPC Tier 2 anim · D-033 fade · monologue spikes) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
walk_away: Walk-away (D-064)\nWASD during conversation {
shape: diamond
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
walk_away_phases: Walk-away Consequences {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
immediate: 1 — Dialogue fades 300ms\n(no close button) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
npc_reacts: 2 — NPC reacts\n(animation · may call after player) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
kg_record: 3 — KG records incompleteness\n(per-seed tolerance: no universal safe-to-leave rules) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
}
player_action -> verb_phase1
verb_phase1 -> verb_phase2: "max verb set" { style.stroke: ${color-accent} }
verb_phase2 -> layer_filter: "filtered verb set" { style.stroke: ${color-accent} }
layer_filter.l1 -> layer_filter.l2
layer_filter.l2 -> layer_filter.l3
layer_filter.l3 -> layer_filter.l4
layer_filter -> invisible_locks: "visible options only\n(max 3 shown)" {
style.stroke: ${color-accent}
}
invisible_locks -> confrontation: "if Confront option present" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
invisible_locks -> walk_away
walk_away -> walk_away_phases.immediate
walk_away_phases.immediate -> walk_away_phases.npc_reacts
walk_away_phases.npc_reacts -> walk_away_phases.kg_record
Binary file not shown.

After

Width:  |  Height:  |  Size: 856 KiB

@@ -0,0 +1,162 @@
# Eavesdrop Pipeline — D-071, D-072, D-078
# Overheard NPC-to-NPC conversation: occlusion filter (server-authoritative),
# ListeningFocus boost, passive dialogue panel, dual-channel principle.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
direction: down
npc_convo: NPC-to-NPC Conversation\n(authored at full fidelity by copy team) {
shape: oval
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
murmur: Universal Murmur Asset (D-072)\nsingle asset plays everywhere {
shape: package
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
zone_ambient: Zone Ambient Level {
shape: diamond
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
conspicuousness: Conversation Conspicuousness {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
bar: Bar (high ambient)\nhidden in murmur, needs proximity {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
workplace: Workplace (moderate)\nsemi-conspicuous, distance-dependent {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
corridor: Corridor (low ambient)\nconspicuous, audible from distance {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
}
server_occlusion: Server-side Occlusion Filter (D-078)\nper-word probability roll {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.border-radius: 4
factors: Factors: distance · ambient noise\n· ListeningFocus stance {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
stochastic: Stochastic per word\n(same scene can yield different fragments) {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
seeded: Seedable RNG per tick\n→ deterministic replay (D-010) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
listen_focus: ListeningFocus Boost (D-071)\nWorld SFX +2 to +3dB\nstationary 30+ ticks {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.border-radius: 4
}
no_ambient_dip: No Ambient Dip for Eavesdrop\n(opposite of direct conversation dip) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
occluded_text: Pre-occluded text\n(words → "..." per roll) {
shape: page
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
passive_panel: Passive Dialogue Panel (D-078)\n(D-061 box, read-only) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.border-radius: 4
speaker_label: Speaker format (e.g. Kael to Mira) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
reduced_opacity: Reduced opacity (0.9)\nvs active dialogue {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
no_responses: No response options {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
monologue_channel: Monologue Channel\n(D-016 — separate pipeline) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
witness_trigger: witness_interaction trigger\n→ character's reaction {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
separate: Character reaction\n(thought · never quoted speech) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
kg_entry: KnowledgeGraph entry\n(KnowsOf confidence unless\nListeningFocus + proximity → KnowsDetails) {
shape: cylinder
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
npc_convo -> murmur: "audio" { style.stroke: ${color-stroke} }
npc_convo -> zone_ambient: "text goes through" { style.stroke: ${color-accent} }
murmur -> zone_ambient: "conspicuousness shaped by" { style.stroke: ${color-stroke} }
zone_ambient -> conspicuousness
zone_ambient -> server_occlusion: "noise penalty" { style.stroke: ${color-stroke} }
listen_focus -> server_occlusion: "probability curve shift" { style.stroke: ${color-accent} }
no_ambient_dip -> listen_focus: "instead of dip" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
server_occlusion -> occluded_text: "pre-occluded text sent to client" { style.stroke: ${color-accent} }
occluded_text -> passive_panel: "client renders exactly what it receives" { style.stroke: ${color-accent} }
passive_panel -> monologue_channel: "triggers witness_interaction" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
passive_panel -> kg_entry: "overheard info enters KG" { style.stroke: ${color-accent} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 826 KiB

@@ -0,0 +1,185 @@
# Perception Pipeline — D-011, D-017, D-018, D-019, D-059, D-060, D-067
# From simulation ECS through to rendered fog and monologue.
# Covers: fog of perception, LOS (D-035), perception modes, three-range sound,
# fog layers, cognitive delay, recognition chime.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
direction: down
world: ECS World State {
shape: hexagon
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
los: LOS System\n(Albert Ford symmetric shadowcasting — D-035) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.border-radius: 4
fov: compute_fov(is_opaque, origin, range, z)\n→ VisibilityMap {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
symmetry: Symmetry guarantee:\nif A sees B → B sees A {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
perception_modes: Perception Modes (D-017) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
natural: Natural Vision\n(walls block, cone model) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
thermal: Thermal\n(heat through walls, no identity) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
camera: Camera Feeds\n(remote, spoofable) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
unisphere: Unisphere Tracking\n(known inserts, maskable) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
audio_analysis: Audio Analysis\n(signatures, no visual) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
}
sound: Sound System (D-018)\nThree-Range Model {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
close: Close (in/near LOS)\nHigh accuracy · stereo audio {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
medium: Medium (outside LOS)\nVisual indicators at fog edge + monologue {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
long: Long (across map)\nInsert notifications · spoofable {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
}
snapshot: ObserverSnapshot {
shape: queue
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
kg_read: KnowledgeGraph read\n(per-character — what THIS observer knows) {
shape: cylinder
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
fog: Fog Rendering (D-059)\n5-layer shader system {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
clear: Clear (vision cone)\nsoft gradient 6-8 sim tiles {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
light_fog: Light Fog (peripheral)\ndesaturated 40-50%, Perlin noise {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
deep_fog: Deep Fog (explored)\nnear-monochrome + zone tint {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
unexplored_maps: Unexplored (has maps)\ngeometric wireframe outlines {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
unexplored_dark: Unexplored (no maps)\nsolid near-black {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
recognition: Fog Entity Recognition {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
chime: Recognition chime fires (D-067)\nat ONSET of cognitive delay {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
delay: Cognitive delay (D-060)\n0.6s base · 0.3s for anomaly {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
monologue_fire: Monologue fires DURING delay\n"Those footsteps... that's Kael's walk" {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
transition: Grey blob → D-033 color\n+ silhouette over 0.3s {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
world -> los: "entity positions + opaque tiles" { style.stroke: ${color-accent} }
world -> sound: "sound events" { style.stroke: ${color-stroke} }
los -> perception_modes: "VisibilityMap" { style.stroke: ${color-accent} }
perception_modes -> snapshot: "observer query result\n(what this sensor reveals)" {
style.stroke: ${color-accent}
}
sound -> snapshot: "sound events" { style.stroke: ${color-stroke} }
kg_read -> snapshot: "per-entity recognition data" { style.stroke: ${color-accent} }
snapshot -> fog: "visible entities + fog state" { style.stroke: ${color-accent} }
snapshot -> recognition: "heard/sensed entity not in LOS" { style.stroke: ${color-stroke} }
recognition.chime -> recognition.delay: "concurrent" { style.stroke: ${color-accent} }
recognition.delay -> recognition.monologue_fire
recognition.delay -> recognition.transition
Binary file not shown.

After

Width:  |  Height:  |  Size: 912 KiB

+101
View File
@@ -0,0 +1,101 @@
# Dialogue + Monologue Tag Taxonomy — D-035, D-028
# Converged tag schema for tagged line pools.
# Structural tags (required), selection tags (recommended), monologue additions.
# Includes Sprint 8 + 14 + 15 amendments.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
dialogue_line: Dialogue Line {
shape: sql_table
id: "{npc-slug}_{d|m}_{###}" {constraint: primary_key}
text: String
role: enum (template-defined role)
access: list<enum> (public · insider · authority · peer · hostile)
trust: enum (surface · real · secret)
situation: list<enum> (14 situations)
topic: list<enum> (9 topics — optional)
mood: list<enum> (8 moods — optional)
tags: list<string> (freeform — optional)
}
monologue_line: Monologue Line {
shape: sql_table
id: "{npc-slug}_m_{s|d}_{###}" {constraint: primary_key}
character: enum (smuggler · detective) {constraint: not_null}
trigger: enum (9 triggers) {constraint: not_null}
prerequisite: map or null
dual_lens: map (authoring-only)
notes: String (authoring-only)
}
access_values: AccessTier values {
shape: sql_table
public: Public — default, anyone
insider: Insider — social network member
authority: Authority — institutional role
peer: Peer — known colleague
hostile: Hostile — adversarial context
}
trust_values: TrustTier values {
shape: sql_table
surface: Surface — any relationship + any confidence
real: Real — (Friendly|Known) + KnowsOf+
secret: Secret — Friendly + KnowsDetails+
}
situation_values: Situation (14) {
shape: sql_table
s1: first_meeting
s2: regular_contact
s3: after_conflict
s4: work_context
s5: social_context
s6: private_context
s7: witnessed_something
s8: under_suspicion
s9: post_confrontation
s10: trust_broken
s11: urgent
s12: relaxed
s13: farewell
s14: greeting
}
mood_values: Mood (8) {
shape: sql_table
m1: anxious
m2: frustrated
m3: content
m4: suspicious
m5: warm
m6: hostile
m7: relieved
m8: focused
}
trigger_values: Monologue Triggers (9) {
shape: sql_table
t1: enter_location
t2: observe_npc
t3: hear_sound
t4: observe_anomaly
t5: post_conversation
t6: discover_evidence
t7: witness_interaction
t8: time_idle
t9: return_visit
}
dialogue_line -> access_values: "access field" { style.stroke: ${color-accent} }
dialogue_line -> trust_values: "trust field" { style.stroke: ${color-accent} }
dialogue_line -> situation_values: "situation field" { style.stroke: ${color-stroke} }
dialogue_line -> mood_values: "mood field" { style.stroke: ${color-stroke} }
monologue_line -> dialogue_line: "extends" { style.stroke: ${color-accent} }
monologue_line -> trigger_values: "trigger field" { style.stroke: ${color-accent} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 753 KiB

+88
View File
@@ -0,0 +1,88 @@
# Knowledge Graph Data Model — D-041
# Per-entity bevy_ecs Component with BTreeMap storage.
# Confidence hierarchy, knowledge state, knowledge source, event-driven updates.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
KnowledgeGraph: KnowledgeGraph {
shape: sql_table
entity_knowledge: BTreeMap<StableId, EntityKnowledge>
fact_knowledge: BTreeMap<FactId, FactKnowledge>
}
EntityKnowledge: EntityKnowledge {
shape: sql_table
stable_id: StableId(u64) {constraint: foreign_key}
confidence: KnowledgeConfidence
state: KnowledgeState
source: KnowledgeSource
last_observed_tick: u64
}
FactKnowledge: FactKnowledge {
shape: sql_table
fact_id: FactId {constraint: primary_key}
confidence: KnowledgeConfidence
state: KnowledgeState
source: KnowledgeSource
last_observed_tick: u64
}
KnowledgeConfidence: KnowledgeConfidence {
shape: sql_table
direct: Direct — currently in LOS
knows_details: KnowsDetails — actionable (secret tier)
knows_of: KnowsOf — involved in Y (real tier)
suspects: Suspects — something off (surface tier)
}
KnowledgeState: KnowledgeState {
shape: sql_table
active: Active — believed true
contradicted: Contradicted — conflict detected (Sprint 3+)
stale: Stale — aged beyond threshold (Sprint 3+)
}
KnowledgeSource: KnowledgeSource {
shape: sql_table
direct_observation: DirectObservation
heard: Heard
told_by: ToldBy (Sprint 3+)
inferred: Inferred (Sprint 3+)
background: Background
}
EntityRegistry: EntityRegistry {
shape: sql_table
stable_to_entity: BTreeMap<StableId, Entity>
entity_to_stable: BTreeMap<Entity, StableId>
}
KnowledgeEventQueue: KnowledgeEventQueue\n(bevy_ecs Resource) {
shape: queue
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
KnowledgeGraph -> EntityKnowledge: "contains many"
KnowledgeGraph -> FactKnowledge: "contains many"
EntityKnowledge -> KnowledgeConfidence: "uses"
EntityKnowledge -> KnowledgeState: "uses"
EntityKnowledge -> KnowledgeSource: "uses"
FactKnowledge -> KnowledgeConfidence: "uses"
FactKnowledge -> KnowledgeState: "uses"
FactKnowledge -> KnowledgeSource: "uses"
EntityKnowledge -> EntityRegistry: "StableId lookup" {
style.stroke: ${color-accent}
style.stroke-dash: 4
}
KnowledgeEventQueue -> KnowledgeGraph: "drained each tick\n→ writes components" {
style.stroke: ${color-accent}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 667 KiB

+154
View File
@@ -0,0 +1,154 @@
# NPC Generation Model — D-024, D-025
# 10 axes + combat component. Social site / functional cluster as atomic template unit.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
direction: right
npc: NPC (generated) {
shape: person
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
essential: 7 Essential Axes {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
want: Want {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
secret: Secret / Vulnerability {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
relationships: Relationships (1-3) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
tolerance: Tolerance Threshold {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
routine: Daily Routine {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
info_inv: Information Inventory {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
contentment: Contentment {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
supporting: 3 Supporting Axes {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
personality: Personality Traits (2-3) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
tell: Tell System {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
skills: Skill Set {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
combat_comp: CombatCapability\n(optional ECS component) {
shape: package
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.stroke-dash: 4
}
key_interactions: Key Contradiction Interactions {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
i1: Want × Secret {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
i2: Routine × Secret {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
i3: Tolerance × Relationships {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
i4: Want × Relationships {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
i5: Personality × Tolerance {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
social_site: Social Site\n(atomic Tier 2 template unit) {
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
group: Social Group (4-8 NPCs)\n2+ triangles + 1 cross-template triangle {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
cluster: Functional Cluster\n15-40 tiles, internal sightlines {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
ownership: NPC Ownership\nowned by 1 template, referenced by others {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
npc -> essential: "generated with" { style.stroke: ${color-accent} }
npc -> supporting: "generated with" { style.stroke: ${color-stroke} }
supporting.skills -> combat_comp: "combat tag → component" {
style.stroke: ${color-accent}
style.stroke-dash: 4
}
essential -> key_interactions: "produces" { style.stroke: ${color-stroke} }
npc -> social_site: "placed in" { style.stroke: ${color-accent} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 634 KiB

+152
View File
@@ -0,0 +1,152 @@
# Knowledge Confidence State Machine — D-041
# 4-level confidence hierarchy with state tracking and decay.
# Maps to dialogue trust tiers (D-075) and fog recognition (D-059).
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
none: No Knowledge\n(entity unknown) {
shape: oval
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
suspects: Suspects\n"something off" {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
knows_of: KnowsOf\n"X is involved in Y" {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
knows_details: KnowsDetails\n"actionable detail" {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
direct: Direct\n"currently in LOS" {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.bold: true
}
dialogue_gates: Dialogue Trust Gate (D-075) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
surface: Surface tier\n(any confidence) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
real: Real tier\n(KnowsOf+ AND Friendly/Known) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
secret: Secret tier\n(KnowsDetails+ AND Friendly) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
}
fog_gate: Fog Recognition (D-059) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
recognized: Recognized entity\n(D-033 color + silhouette) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
unrecognized: Grey blob\n(no identity) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
knowledge_states: KnowledgeState {
shape: package
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
active: Active (Sprint 2) {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
contradicted: Contradicted (Sprint 3+)\nToldBy conflicts DirectObservation {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
stale: Stale (Sprint 3+)\naged past DecayThreshold {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
}
none -> suspects: "observe anomaly\nor receive tip" {
style.stroke: ${color-stroke}
}
suspects -> knows_of: "further observation\nor testimony" {
style.stroke: ${color-stroke}
}
knows_of -> knows_details: "direct evidence\nor confrontation" {
style.stroke: ${color-accent}
}
knows_details -> direct: "enter LOS" {
style.stroke: ${color-accent}
}
direct -> knows_details: "exit LOS" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
# Decay path (D-041: once per game-minute)
knows_details -> knows_of: "decay\n(last_observed_tick age)" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
knows_of -> suspects: "decay" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
suspects -> dialogue_gates.surface
knows_of -> dialogue_gates.real
knows_details -> dialogue_gates.secret
suspects -> fog_gate.unrecognized
knows_of -> fog_gate.recognized
knows_details -> fog_gate.recognized
knows_details -> knowledge_states.contradicted: "ToldBy vs DirectObservation\n(Sprint 3+)" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
knows_of -> knowledge_states.stale: "decay (Sprint 3+)" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
none -> knowledge_states.active
Binary file not shown.

After

Width:  |  Height:  |  Size: 638 KiB

+111
View File
@@ -0,0 +1,111 @@
# Movement Stance State Machine — D-053, D-054, D-055
# Toggle ladder: Sprint / Walk / Careful / Crouch / (Prone future).
# Server-authoritative tile-based movement. Client Tween interpolation.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
sprint: Sprint {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.bold: true
}
sprint_detail: 1 tile/tick · loud footsteps\nMonologue 40% (urgent only)\nInteraction buffer CLEARED (D-055)\nSprint double-take: anomaly monologue fires retroactively {
shape: page
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
walk: Walk\n(default stance) {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
walk_detail: 1 tile/2 ticks · normal footsteps\nMonologue 100%\nDefault — MovementProfile component {
shape: page
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
careful: Careful {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
careful_detail: 1 tile/3 ticks · quiet footsteps\nMonologue 150% + tell notice bonus\nListeningFocus accumulates (stationary_ticks)\nEavesdrop bonus: ListeningFocus +2-3dB (D-071) {
shape: page
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
crouch: Crouch {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
crouch_detail: 1 tile/4 ticks · very quiet\nUses Prone/Seated occupancy layer (D-054) {
shape: page
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
prone: Prone\n(future) {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 5
}
tile_occupancy: TilePresence (D-054)\nSame-tile occupancy layers {
shape: package
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
standing: Standing {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
prone_layer: Prone / Seated {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
fixture_layer: Fixture {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
sprint -> sprint_detail
walk -> walk_detail
careful -> careful_detail
crouch -> crouch_detail
sprint -> walk: "toggle" { style.stroke: ${color-accent} }
walk -> sprint: "toggle" { style.stroke: ${color-accent} }
walk -> careful: "toggle" { style.stroke: ${color-stroke} }
careful -> walk: "toggle" { style.stroke: ${color-stroke} }
careful -> crouch: "toggle" { style.stroke: ${color-stroke} }
crouch -> careful: "toggle" { style.stroke: ${color-stroke} }
crouch -> prone: "toggle (future)" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
prone -> crouch: "toggle-out only" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
crouch -> tile_occupancy.prone_layer: "occupies" { style.stroke: ${color-stroke} }
walk -> tile_occupancy.standing: "occupies" { style.stroke: ${color-stroke} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

@@ -0,0 +1,96 @@
# NPC Simulation Tier State Machine — D-026
# bevy_ecs dynamic component add/remove makes tier transitions seamless.
# Scope tags keep NPCs in Active tier.
vars: {
color-bg: "#2a3040"
color-stroke: "#333340"
color-text: "#c8d0e0"
color-accent: "#c8d8f0"
color-dim: "#1a1e24"
}
ungenerated: Tier 4\nUngenerated {
style.fill: ${color-dim}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 5
}
state_saved: Tier 3\nState-Saved\n~1-2KB frozen struct {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
background: Tier 2\nBackground\n500-2,000 NPCs {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
active: Tier 1\nActive\n30-80 NPCs · full sim {
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
style.bold: true
}
scope_tags: Scope Tags (prevent eviction) {
shape: package
style.fill: ${color-dim}
style.stroke: ${color-accent}
style.font-color: ${color-text}
neighborhood: neighborhood {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
active_quest: active-quest {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
colleague: colleague {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
known_contact: known-contact {
style.fill: ${color-bg}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
lru: LRU Priority Queue\n(interaction-timestamp) {
shape: diamond
style.fill: ${color-bg}
style.stroke: ${color-accent}
style.font-color: ${color-text}
}
ungenerated -> state_saved: "player approach\n(generated ahead)" {
style.stroke: ${color-stroke}
}
state_saved -> background: "player return\n(~2-5ms reactivation)" {
style.stroke: ${color-stroke}
}
background -> state_saved: "LRU eviction" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
background -> active: "player proximity\nor scope tag match" {
style.stroke: ${color-accent}
}
active -> background: "LRU eviction\n(no scope tag)" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
scope_tags -> active: "prevents eviction" {
style.stroke: ${color-accent}
style.stroke-dash: 4
}
lru -> active: "manages" { style.stroke: ${color-accent} }
lru -> background: "manages" { style.stroke: ${color-stroke} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

+108
View File
@@ -0,0 +1,108 @@
# Fog System — Five Layers + Entity Rendering in Fog — D-059
# Shader-based, knowledge-graph-driven. Covers all five fog states
# and the entity types rendered within fogged areas.
vars: {
color-screen: "#1a1e24"
color-panel: "#2a3040"
color-text: "#c8d0e0"
color-nav: "#c8d8f0"
color-stroke: "#333340"
}
direction: right
kg_read: KnowledgeGraph\n(per character — D-041) {
shape: cylinder
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
fog_layers: Five Fog Layers {
style.fill: ${color-screen}
style.stroke: ${color-nav}
style.font-color: ${color-text}
l1: Layer 1 — Clear (vision cone)\nSoft gradient edge 6-8 sim tiles\n(= 3-4 visual tiles per D-066)\nNo hard line · Darkwood approach {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
style.bold: true
}
l2: Layer 2 — Light Fog (peripheral)\nDesaturated 40-50% · brightness -30%\nAnimated Perlin noise (8-10s cycle)\nD-033 entity colors visible but reduced {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l3: Layer 3 — Deep Fog (explored)\nNear-monochrome + ~10% zone tint\n(bar=warm dark · hub=cool dark)\nMore pronounced noise (15-20s cycle)\nzone_id from ObserverSnapshot (D-077) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l4: Layer 4 — Unexplored (has maps)\nGeometric wireframe outlines\nInsert data aesthetic {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l5: Layer 5 — Unexplored (no maps)\nSolid near-black\nInformation zero {
style.fill: ${color-screen}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
fog_entities: Entities in Fog {
style.fill: ${color-screen}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
sound_ping: Sound Ping\n2-3 concentric expanding rings\n(sonar-style · insert white-blue)\nLoud=3 rings bright · quiet=1 ring faint\nFade over 1.5s {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
recognized: Recognized Entity\nD-033 color glow + silhouette feature\n(e.g. identifying clothing detail)\n0.8s breathing pulse\n+/-0.5 tile position drift {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
unrecognized: Unrecognized Entity\nneutral grey blob\nno silhouette · no identity {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
divergence: "Same fog, different information per character\nSmuggler: recognizes dock workers = green icons\nDetective: same entities = grey blobs\n\nFog is not darkness —\nit is the absence of your attention." {
shape: page
style.fill: ${color-screen}
style.stroke: ${color-nav}
style.font-color: ${color-text}
style.italic: true
}
perf: Performance Budget\n<1ms/frame total\nVision cone = PointLight2D\nFog = CanvasGroup noise shader (Layer 5)\nSound pings = 0-5 sprites\nEntity ghosts = 0-10 sprites typical {
shape: package
style.fill: ${color-screen}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
kg_read -> fog_layers: "determines entity recognition\n(which observer sees which entities)" {
style.stroke: ${color-nav}
}
kg_read -> fog_entities.recognized: "KnowsOf+ → recognized" {
style.stroke: ${color-nav}
}
kg_read -> fog_entities.unrecognized: "Suspects / none → blob" {
style.stroke: ${color-stroke}
}
fog_layers -> fog_entities: "entities rendered within fog state" {
style.stroke: ${color-stroke}
}
fog_layers -> divergence: "same shader, per-character KG" {
style.stroke: ${color-nav}
style.stroke-dash: 4
}
fog_layers -> perf
Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

+146
View File
@@ -0,0 +1,146 @@
# HUD Layout and Z-Stack — D-049, D-048, D-061, D-076
# 8-layer z-stack, insert overlay, dialogue box constraints.
# Dual-scale grid context: 64x64px visual tiles (D-066).
vars: {
color-screen: "#1a1e24"
color-panel: "#2a3040"
color-text: "#c8d0e0"
color-nav: "#c8d8f0"
color-stroke: "#333340"
}
direction: down
zstack: Rendering Z-Stack (D-049)\n8 layers — bottom to top {
style.fill: ${color-screen}
style.stroke: ${color-nav}
style.font-color: ${color-text}
l0: Layer 0 — Floor Tiles\n(zone identity · movement surface) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l1: Layer 1 — Floor Objects\n(cosmetic · walked over) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l2: Layer 2 — Furniture / Placed Objects\n(y-sorted with entities) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l3: Layer 3 — Entity Sprites\n(y-sorted · D-033 relationship color\n24x32px footprint in 64x64 tile) {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
l4: Layer 4 — Overhead / Wall Tops\n(pipes · ducts · fixtures · signage\nsemi-transparent partial occlusion) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
l5: Layer 5 — Fog of Perception\n(vision cone mask · fog shader\naffects layers 0-4) {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
l6: Layer 6 — Insert Overlay\n(lattice HUD · bloom-rendered\nNOT affected by fog\nInteraction labels render here) {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
l7: Layer 7 — Monologue / UI\n(always visible · top of stack\nDialogue box and response options) {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
style.bold: true
}
}
insert_overlay: Insert Overlay Design (D-048) {
style.fill: ${color-screen}
style.stroke: ${color-nav}
style.font-color: ${color-text}
bloom: Soft bloom shader\n~2-3px gaussian · ~40% blend {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
smuggler_overlay: Smuggler\nthinner · sparser (baseline lattice) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
detective_overlay: Detective\ndenser · crisper (augmented lattice) {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
insert_off: Insert OFF behavior (OQ-07)\nCursor shape changes\nInteraction labels hidden {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
}
dialogue_box: Dialogue Box (D-061, D-076) {
style.fill: ${color-screen}
style.stroke: ${color-nav}
style.font-color: ${color-text}
position: Bottom of screen\nmax 20% height {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
max_width: Max-width 1200px\n(centered · ~62% of 1920px) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
log: Unified conversation log\n(active + overheard — chronological) {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
speaker_format: Speaker to Target format\nper-character name colours {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
responses: Response options below log\nmax 3 visible {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
no_portraits: No portraits\n(NPC is on screen) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
timeout: Entry timeout\n15s + 3s fade (configurable) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
monologue_position: Monologue floats ABOVE dialogue box\n(z-layer 7 — spatial separation\ncharacter thinks while NPC speaks) {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
style.border-radius: 4
}
zstack.l5 -> insert_overlay: "does NOT affect" {
style.stroke: ${color-nav}
style.stroke-dash: 4
}
zstack.l6 -> insert_overlay: "rendered at" { style.stroke: ${color-nav} }
zstack.l7 -> dialogue_box: "rendered at" { style.stroke: ${color-nav} }
dialogue_box -> monologue_position: "monologue above" { style.stroke: ${color-nav} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 678 KiB

+153
View File
@@ -0,0 +1,153 @@
# Interaction UI Flow — D-056, D-057, D-058
# Cursor states, entity interaction list, world radial menu.
# All insert-styled: geometric, bloom, diegetic.
vars: {
color-screen: "#1a1e24"
color-panel: "#2a3040"
color-text: "#c8d0e0"
color-nav: "#c8d8f0"
color-stroke: "#333340"
}
direction: down
cursor: Cursor States (D-056)\n(insert's own interface element · z-layer 7) {
style.fill: ${color-screen}
style.stroke: ${color-nav}
style.font-color: ${color-text}
default_cursor: Default\n4 thin inward ticks + bloom\nWhite-blue · barely visible {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
entity_hover: Entity Hover\nTicks expand outward (150ms)\nCorner brackets · D-033 relationship color\nVerb tooltip in insert styling {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
object_hover: Object Hover\nTicks rotate 45° → X-shape\nMuted grey (amber if flagged) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
weapon_aim: Weapon Aim\nTicks extend · center gap widens\nLines 1 to 2px · warm white\nNO bloom · D-033 tint on target {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
}
cursor_rules: Cursor Rules {
style.fill: ${color-screen}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
los_trigger: Changes on LOS · not just proximity {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
range: Interaction range ~2 sim tiles (= 1m) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
weapon_suppress: Weapon mode suppresses interaction prompts\n(unless Shift held) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
insert_off: Insert OFF: cursor shape still changes\n(body reacts) · verb labels hidden\n(insert doesn't process targets) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
}
entity_list: Entity Interaction List (D-057)\n(left-click on entity) {
style.fill: ${color-screen}
style.stroke: ${color-nav}
style.font-color: ${color-text}
format: Compact vertical list\nanchored to entity position\n2-4 options max {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
new_glow: New options: gradient glow background\n(knowledge change signal) {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
z_layer: Labels on z-layer 6\n(insert data — hidden if insert off) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
phase1: Phase 1 (simulation): max verb set\nfrom ObjectType component {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
phase2: Phase 2 (observer): filter by KG\narchetype variation · POI flip {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
}
}
world_menu: World Radial Menu (D-058)\n(right-click) {
style.fill: ${color-screen}
style.stroke: ${color-nav}
style.font-color: ${color-text}
v01_spokes: v0.1: 2 spokes\nObserve (eye) · Insert (phone) {
style.fill: ${color-panel}
style.stroke: ${color-nav}
style.font-color: ${color-text}
style.bold: true
}
future_spokes: Future: up to 6 spokes\n+ Comms (signal) · Wait (clock) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
style.stroke-dash: 4
}
input: Drag-release (power users)\nClick-click (newcomers) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
why_radial: Fixed categories → spatial memory\n(unlike entity verbs which vary by knowledge) {
style.fill: ${color-panel}
style.stroke: ${color-stroke}
style.font-color: ${color-text}
}
}
cursor.default_cursor -> cursor.entity_hover: "entity in LOS\n+ proximity" {
style.stroke: ${color-nav}
}
cursor.default_cursor -> cursor.object_hover: "object in LOS\n+ proximity" {
style.stroke: ${color-stroke}
}
cursor.entity_hover -> cursor.weapon_aim: "weapon selected" {
style.stroke: ${color-nav}
}
cursor.weapon_aim -> cursor.entity_hover: "weapon deselected" {
style.stroke: ${color-stroke}
style.stroke-dash: 4
}
cursor.entity_hover -> entity_list: "left-click\n→ shows interaction list" {
style.stroke: ${color-nav}
}
cursor.default_cursor -> world_menu: "right-click\n→ opens radial" {
style.stroke: ${color-nav}
}
cursor -> cursor_rules
entity_list.phase1 -> entity_list.phase2: "filtered" { style.stroke: ${color-nav} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 868 KiB