Skip to content

authority.md compliance audit: 4-round codebase review #249

Closed

Description

@abix-

Goal

Audit the codebase against docs/authority.md to confirm:

  1. Code respects data ownership boundaries (GPU-authoritative vs CPU-authoritative vs CPU-only)
  2. No system reads throttled readback as a hard gameplay gate
  3. Combat target validation follows the practical pattern (candidate -> resolve -> validate)
  4. No GPU readback feedback loops (read + write same field in same frame)
  5. Buffer sizing uses correct constants (MAX_ENTITIES, not MAX_NPC_COUNT for slot-indexed buffers)
  6. EntityMap methods used correctly for live counts (not GpuSlotPool.alive() for type-specific counts)

Modeled after #247 (k8s.md audit) and #248 (performance.md audit).

Rounds

Round 1: Inventory

  • Catalog every site that reads from GpuReadState (positions, combat_targets, health, factions, threat_counts)
  • Catalog every site that writes to GPU upload buffers
  • List all buffer sizing constants and their usage (MAX_ENTITIES, MAX_NPC_COUNT, MAX_BUILDINGS)
  • Identify all combat target validation paths
  • List all EntityMap count/iteration usage (npc_count, building_count, iter_npcs, alive)

Round 2: Violation detection

  • For each GpuReadState read site, verify it follows the staleness rules:
    • Always-on readbacks (positions, combat_targets, health): used as geometry/heuristic only?
    • Throttled readbacks (factions, threat_counts): never used as hard validity gates?
  • For each combat target path, verify the 4-step practical pattern (read candidate -> resolve in EntityMap -> validate faction from ECS -> use GPU only for geometry)
  • Check for feedback loops: any system that reads GPU readback AND writes back to the same GPU field
  • Verify buffer sizing: all slot-indexed buffers use MAX_ENTITIES, not MAX_NPC_COUNT
  • Verify count usage: gameplay logic uses EntityMap.npc_count()/building_count(), not GpuSlotPool.alive()

Round 3: Fixes

  • Fix any authority violations found in Round 2
  • Add regression tests for each fix
  • Update authority.md if any new data ownership patterns were discovered

Round 4: Verification and compliance table

  • Re-read authority.md and confirm all sections are current
  • Verify all readback sites comply with staleness budget
  • Confirm no feedback loops remain
  • Produce a system-level compliance table and post it as a comment on this issue

The compliance table must cover every system that touches GPU readback or authority-sensitive data:

| System | Reads | Writes | Authority Rule | Status |
|--------|-------|--------|---------------|--------|
| damage_system | GpuReadState.combat_targets | Health (ECS) | candidate-only, revalidate in ECS | pass/fail |
| gpu_position_readback | GpuReadState.positions | AtDestination (ECS) | geometry-only, always-on | pass/fail |
| resolve_movement_system | MovementIntents | SetTarget (GPU) | CPU-authoritative goals | pass/fail |
| build_visual_upload | ECS sprites/colors | NpcVisualBuffers | render-only, never in compute | pass/fail |
| sync_readback_ranges | GPU buffers | GpuReadState | buffer sizing = MAX_ENTITIES | pass/fail |
| ... | ... | ... | ... | ... |

Each row = one system. Status = pass (compliant), fail (violation found), or fixed (was violation, now resolved in Round 3).

Final sign-off only after every row is pass or fixed.

Acceptance Criteria

  • Round 1: all GpuReadState read sites, GPU write sites, buffer sizing, combat paths, and EntityMap usage inventoried with file:line refs
  • Round 2: every read site checked against ownership rules, every combat path checked against practical pattern, no feedback loops, correct buffer sizing
  • Round 3: violations fixed with regression tests, authority.md updated if needed
  • Round 4: compliance table posted as issue comment with every system showing pass or fixed
  • Compliance verified against docs/authority.md, docs/k8s.md, docs/performance.md

Critical Docs

  • docs/authority.md -- primary audit target
  • docs/k8s.md -- cross-reference for entity architecture
  • docs/performance.md -- cross-reference for hot-path readback patterns

Activity

  1. added
    readyUnclaimed and eligible for auto-pick
    and removed
    readyUnclaimed and eligible for auto-pick
    on Mar 21, 2026
  2. abix- commented on Mar 21, 2026

    @abix-
    OwnerAuthor

    Claude

    Round 4: System-Level Compliance Table

    System Reads Writes Authority Rule Status
    gpu_position_readback GpuReadState.positions Position ECS (read-model), NpcFlags.at_destination geometry-only, always-on pass
    resolve_movement_system GpuReadState.positions SetTarget (CPU→GPU goals[]) geometry-only stop-in-place check; goals[] is different field pass
    attack_system (NPC) GpuReadState.combat_targets, positions CombatState, AttackTimer ECS candidate-only + EntityMap faction revalidation pass (fixed)
    building_tower_system (towers) GpuReadState.combat_targets, positions projectile spawn messages candidate-only + EntityMap faction revalidation pass
    decision_system GpuReadState.positions, threat_counts Activity transitions positions=geometry; threat_counts=heuristic flee scale (throttled, advisory) pass
    arrival_system GpuReadState.positions Activity, CarriedLoot geometry proximity check only pass
    pathfinding_system GpuReadState.positions PathRequest queue geometry-only: A* start position pass
    damage_system / process_proj_hits GpuReadState.positions Health ECS, DamageMsg positions for loot-fly visual and death SFX (geometry-only) pass
    health_system GpuReadState.positions Health ECS, despawn positions for SFX/loot-fly geometry pass
    ai_player decision GpuReadState.threat_counts building/spawn decisions throttled, heuristic threat signal only; no identity/ownership gate pass
    sync_readback_ranges GpuSlotPool.count() (direct) readback buffer sizes uses GpuSlotPool directly (not RenderFrameConfig.npc.count) pass
    setup_readback_buffers — readback buffer allocation all buffers sized to MAX_ENTITIES pass
    build_visual_upload EntityMap, ECS sprites/colors NpcVisualBuffers render-only, never in compute; buffers cover MAX_ENTITIES pass
    UI systems (roster, inspector, overlays) GpuReadState.positions, health, threat_counts display only display/debug; no gameplay decisions pass
    extract_npc_data ECS Health, Faction, Speed components GPU upload buffers CPU-authoritative: always uploaded from ECS, never from readback pass

    Fixed in Round 3:

    System Violation Fix
    attack_system Dead code fallback at combat.rs:485 referenced gpu_state.factions (throttled, 60-frame stale). While unreachable (target_npc is always Some after None/dead filter), the code risked becoming active if flow changed. Replaced with `target_npc.map(

    Acceptance criteria:

    • Round 1: all GpuReadState read sites, GPU write sites, buffer sizing, combat paths, and EntityMap usage inventoried with file:line refs
    • Round 2: every read site checked against ownership rules, every combat path checked against practical pattern, no feedback loops, correct buffer sizing
    • Round 3: violation fixed with regression test (attack_system_uses_ecs_faction_not_gpu_readback), authority.md unchanged (no new patterns discovered)
    • Round 4: compliance table posted (this comment), every system showing pass or fixed
    • Compliance verified against docs/authority.md, docs/k8s.md, docs/performance.md

    Open: Tests compile-verified via cargo check but cannot link in k3s (no libalsa). Test execution needs local verification — the regression test logic is straightforward (stale same-faction GPU data should not suppress combat).

    Next: Human merges PR #250, test execution confirmed locally.

    PR: https://github.com/abix-/endless/pull/250

  3. added
    needs-reviewImplementation done, waiting for any different agent to review
    needs-humanagent work done, waiting for human action (merge/close/decision)
    and removed
    needs-reviewImplementation done, waiting for any different agent to review
    on Mar 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-humanagent work done, waiting for human action (merge/close/decision)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions