# 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
