synvael/AGENTS.md

5.1 KiB

AGENTS.md

CRITICAL: This file contains the engineering context for AI coding agents.

🚨 Absolute Rules (Never Break These) / Do Not

  • DO NOT bypass the Lua scripting layer for gameplay logic.
  • DO NOT use unwrap() or expect() outside main or tests.
  • DO NOT use println!; use tracing.
  • DO NOT introduce non-deterministic logic into worldgen (no thread_rng, no HashMap iteration).
  • DO NOT build parallel registration systems or duplicate registries.

📖 What to Read

  • Read AGENTS.md (this file) first for every task.
  • Read DEVELOPMENT.md before making any architectural or cross-cutting changes.
  • Read subsystem docs (docs/ and rustdoc) only for the specific crates you are modifying.

Before Changing Code

  • Does this require updates to documentation or ADRs (docs/adr/)?
  • Which crate does this belong to? (Maintain strict boundaries).
  • Is this a new gameplay feature? If so, it must be exposed via the Lua API.

🛠️ Modification Priorities

  1. Implement the feature in Lua if possible, using existing APIs.
  2. Extend the Lua API if it lacks the required capability.
  3. Modify Rust internals only as a last resort to support the Lua API. Avoid bypassing the scripting layer entirely for gameplay features.

🏗️ Code Style & Edits

  • Prefer modifying existing systems over creating new abstractions.
  • Avoid duplicate registries, parallel APIs, unnecessary traits, and premature generic abstractions.
  • Keep changes local to the relevant module unless the architecture requires otherwise.

When Unsure

If an implementation conflicts with these rules, prefer preserving the architecture over minimizing code changes.

📦 Architectural Dependency Rules

  • shared stays lean and dependency-light (no mlua, no rendering).
  • scripting depends on shared, but shared does not depend on scripting.
  • client and server depend on shared, scripting, and net.
  • client depends on renderer, but server does not.
  • Do not put simulation logic in client.

🔍 File Location Hints

  • /assets/scripts/: Shipped base game Lua scripts.
  • /mods/: In-repo example mods/test fixtures.
  • <user-data-dir>/mods/: Player-installed mods (resolved at runtime).
  • crates/client/: Windowing, input, presentation.
  • crates/server/: Authoritative simulation.
  • crates/shared/: Core types, network protocols.
  • crates/scripting/: Lua API bindings.
  • crates/renderer/: Vulkan graphics.
  • crates/net/: QUIC networking.

⚙️ Basic Verification Commands

  • Check compilation: cargo check -p <crate>
  • Lint code: cargo clippy --all-targets --all-features -- -D warnings
  • Format Rust: cargo fmt --all -- --check
  • Format Lua: stylua . and selene .
  • Run tests: cargo test -p <crate>

🚀 Quick Start Task Checklist

  • Review "What to Read" and "Before Changing Code".
  • Check modification priorities (Lua vs Rust).
  • Make edits following code style guidelines.
  • Run basic verification commands.
  • Commit using Conventional Commits.

Additional Subsystem Context

Concurrency & State

  • Multithreaded: Prefer message-passing and per-thread ownership over shared mutable state. Avoid large Mutex wrappers.
  • Vulkan queues: Not free-threaded.
  • Lua VMs: Not thread-safe. Treat each VM as owned by a single thread.

Determinism

  • Worldgen: Strictly seed-deterministic. Use fixed RNG algorithms (wyrand, xoshiro). Never use rand::thread_rng(). Do not rely on HashMap iteration order (use BTreeMap or IndexMap).
  • Simulation: Server-authoritative but not lockstep. Platform-specific math and floats are permitted outside of worldgen.

Logging & Error Handling

  • Logging: Use tracing and spans (#[tracing::instrument]). No println!.
  • Libraries (shared, renderer, scripting): Use thiserror.
  • Binaries (client, server): Use anyhow.

Testing Expectations

  • Test pure algorithmic logic, correctness traps (e.g. integer overflow, div_euclid), and determinism (worldgen).
  • I/O and GPU code are tested via integration/visual verification.
  • Ensure new tests run successfully and do not break existing ones.

Linting

  • The workspace uses strict lints (including banning unwrap, expect, print).
  • Prefer #[expect(...)] over #[allow(...)]. Suppress narrowly and justify non-obvious suppressions. Never suppress correctness lints.

Documentation Style

  • Formal, objective tone. No "we" or "you".
  • All public/internal struct fields need /// docs.
  • Functions require # Errors, # Panics, and # Safety sections in that order.

Branching Strategy

  • Development branch: dev.
  • Releases branch: main.
  • Large features: Feature branch off dev (e.g., feat/new-worldgen).

General Coding Standards

  • Content IDs: Strict "namespace:id" format (e.g. "core:stone"). Interned to handles at runtime.
  • Coordinate system: +Y up, right-handed. 1 unit = 1 block (0.5m).
  • Paths: Linux/Windows only. Use std::path::Path and directories crate. No hard-coded /home.
  • Commits: Conventional Commits with crate scope (e.g., feat(scripting): ...).