# Architecture Decision Registry # # PURPOSE: Single source of truth for key architectural stances that all ADRs # must agree on. Skills check this before writing new ADRs to detect conflicts # at authoring time — before stories are created against contradictory decisions. # # RULES: # - Register a stance when it constrains how OTHER systems must be built. # An internal implementation detail that affects only one ADR does not need # to be registered. # - Never delete entries — set status: superseded_by: ADR-NNNN instead. # - When a stance changes: update the entry, set revised: to today's date, # add a comment with the old value, and run /architecture-review to check # what ADRs are now invalidated. # - adr: is the authoritative source. All other ADRs that depend on this # stance list themselves in referenced_by. # # WRITTEN BY: /architecture-decision (Phase 5 — after ADR is approved) # READ BY: /architecture-decision (Step 2 — before authoring begins) # /architecture-review (Phase 4 — cross-ADR conflict baseline) # /create-stories (to embed architectural constraints in stories) # /dev-story (to check implementation against accepted stances) # # SEARCH PATTERNS (for skills using Grep): # All state owners: Grep pattern="^ - state:" path="docs/registry/architecture.yaml" # Who owns player_health: Grep pattern="state: player_health" # All signal contracts: Grep pattern="pattern: signal" # Budget for combat: Grep pattern="system: combat" # All forbidden patterns: Grep pattern="^ - pattern:" (forbidden_patterns section) # Superseded entries: Grep pattern="status: superseded" version: 1 last_updated: "" # ─── STATE OWNERSHIP ───────────────────────────────────────────────────────── # Who is the authoritative owner of each piece of shared game state. # Conflicts: two ADRs claiming to own the same state = data race / authority bug. # # Register state when it is READ or WRITTEN by more than one system. # Internal-only state (never accessed by another system) does not need to be registered. # # Required fields: state, owner_system, adr, interface, referenced_by[], added # interface: how other systems access this state (read-only property, method call, # signal, shared resource, etc.) — this is the contract other ADRs depend on. state_ownership: [] # Example: # # state_ownership: # - state: player_health # status: active # active | superseded_by: ADR-NNNN # owner_system: health-system # adr: docs/architecture/adr-0001-health-system.md # interface: "HealthComponent.current_health (read-only float, range 0–max_health)" # write_access: health-system-only # only owner can write; others read # referenced_by: # - docs/architecture/adr-0001-health-system.md # - docs/architecture/adr-0003-combat-system.md # reads to apply damage # - docs/architecture/adr-0007-ui-system.md # reads to display HUD # added: 2026-03-26 # revised: "" # ─── INTERFACE CONTRACTS ────────────────────────────────────────────────────── # How systems are required to communicate with each other. # Conflicts: one ADR expects signal, another expects direct call = integration bug. # # Register a contract when the communication pattern between two systems is # explicitly decided in an ADR and other systems must follow the same pattern. # # pattern options: signal | direct_call | event_bus | shared_resource | rpc | none interfaces: [] # Example: # # interfaces: # - contract: damage_delivery # status: active # pattern: signal # how the producer notifies consumers # producer: combat-system # consumers: # - health-system # receives damage_dealt signal, applies to health # - ui-system # receives damage_dealt signal, shows damage number # - audio-system # receives damage_dealt signal, plays SFX # adr: docs/architecture/adr-0003-combat-system.md # signal_signature: "damage_dealt(amount: float, target: Node, is_crit: bool)" # referenced_by: # - docs/architecture/adr-0003-combat-system.md # - docs/architecture/adr-0001-health-system.md # added: 2026-03-26 # revised: "" # ─── PERFORMANCE BUDGETS ────────────────────────────────────────────────────── # Frame time allocations per system, against a defined total frame budget. # Conflicts: allocations that sum to more than the total budget = unshippable. # # Register a budget when an ADR explicitly claims a frame time allocation. # The registry lets /architecture-review verify the total doesn't exceed the target. performance_budgets: [] # Example: # # performance_budgets: # - target_fps: 60 # total_frame_budget_ms: 16.6 # platform: PC # PC | Console | Mobile | All # adr: docs/architecture/adr-0000-performance-targets.md # added: 2026-03-26 # revised: "" # # - system: combat # status: active # budget_ms: 2.0 # adr: docs/architecture/adr-0003-combat-system.md # notes: "Includes physics queries, hitbox evaluation, and damage calculation" # referenced_by: # - docs/architecture/adr-0003-combat-system.md # added: 2026-03-26 # revised: "" # ─── API DECISIONS ─────────────────────────────────────────────────────────── # Which engine APIs are chosen for which purpose across the project. # Conflicts: two ADRs using different APIs for the same purpose = inconsistent # implementation that breaks when one system expects the other's API. # # Register an API decision when the choice is non-obvious and other ADRs might # make a different choice for the same purpose without knowing this was decided. api_decisions: [] # Example: # # api_decisions: # - purpose: physics_raycast # status: active # api: PhysicsServer3D.space_get_direct_state() # not: RayCast3D node # explicitly banned for this purpose # adr: docs/architecture/adr-0002-physics-architecture.md # reason: "Direct server calls avoid per-frame node overhead; 3× faster in profiling" # referenced_by: # - docs/architecture/adr-0002-physics-architecture.md # - docs/architecture/adr-0003-combat-system.md # added: 2026-03-26 # revised: "" # ─── FORBIDDEN PATTERNS ────────────────────────────────────────────────────── # Architecture anti-patterns explicitly banned by accepted ADRs. # When writing a new ADR, check this list — if the proposed approach matches # a forbidden pattern, it must be reworked before the ADR can be Accepted. # # Register a pattern when an ADR explicitly bans it AND other ADRs might # unknowingly use it (i.e., it's a tempting but wrong approach for this project). forbidden_patterns: [] # Example: # # forbidden_patterns: # - pattern: autoload_singleton_coupling # status: active # description: "Systems must not directly reference Autoload singletons by name. # Use dependency injection or signals instead." # why: "Tight coupling to Autoloads makes systems untestable in isolation and # creates hidden dependencies that break when Autoload load order changes." # adr: docs/architecture/adr-0001-health-system.md # added: 2026-03-26 # # - pattern: direct_cross_system_state_write # status: active # description: "A system must never write to state owned by another system. # Use signals or method calls on the owner instead." # why: "Direct state writes create race conditions and break the state # ownership model. The owning system must be the sole writer." # adr: docs/architecture/adr-0000-architecture-principles.md # added: 2026-03-26