# DevOps Procedures Operational procedures for building, testing, and running The Settled Reach. ## Repository Layout ``` client/ Godot 4 client (GDScript, scenes, assets) server/ Rust/bevy_ecs simulation server tooling/ Build tools, scripts, asset pipelines tests/ Integration and end-to-end tests (cross-boundary) decisions/ Decision domain files (source of truth for all D/Q/R entries) .config/ Configuration files (linters, formatters, CI) .cache/ Local caches for testing/linting (gitignored) docs/ Design, architecture, briefings, workshops db/ SQLite ticketing + decisions database and connectors ``` Unit tests live inside their respective projects (`server/` uses `#[cfg(test)]` inline + `tests/` directory per D-030). The top-level `tests/` directory is for integration tests that cross the client-server boundary (IPC round-trip, serialization fixtures, divergence tests). ## Prerequisites | Tool | Version | Purpose | |------|---------|---------| | Rust (via rustup) | stable | Server compilation, clippy, rustfmt (auto-installed by `make setup`) | | Godot | 4.x | Client editor and runtime (auto-installed to `~/bin/` by `make setup`) | | Python | 3.x | Tooling scripts, db connectors | | Make | any | Task runner (see below) | | curl | any | Downloading Godot | | unzip | any | Extracting Godot | ## Makefile Targets All development operations go through the top-level `Makefile`. Run `make` with no arguments for a summary. ### Setup ```bash make setup # Install/verify all dev dependencies GODOT_VERSION=4.4 make setup # Pin a specific Godot version ``` Downloads and installs Godot to `~/bin/godot4`, installs Rust clippy + rustfmt, and verifies Python/curl/unzip. Skips the download if the correct version is already installed. The `GODOT_VERSION` variable defaults to `4.6` and can be overridden. ### Build ```bash make build # Build both client and server make build-server # cargo build in server/ make build-client # Client builds are editor-managed (prints guidance) ``` ### Run ```bash make server # cargo run in server/ make client # Launch Godot with client/ project ``` The server must be running before the client connects (subprocess launch will be automated later per D-020). ### Test ```bash make test # Run all tests make test-server # cargo test in server/ make test-client # gdUnit4 tests (headless runner pending) ``` Server tests use Rust's built-in test framework with `#[cfg(test)]` inline tests and `tests/` integration tests (D-030). Client tests use gdUnit4 (D-030). ### Lint ```bash make lint # Run all linters make lint-server # clippy (deny warnings) + rustfmt --check make lint-client # gdlint/gdformat (pending setup) ``` ### CI (Local) Run the full CI pipeline locally before pushing: ```bash make ci # Both pipelines make ci-server # lint-server → build-server → test-server make ci-client # lint-client → build-client → test-client ``` CI targets chain lint → build → test sequentially. A failure in any stage stops the pipeline. ### Clean ```bash make clean # Remove build artifacts and .cache/ contents ``` ### Content Validation ```bash make validate-content # Validate content YAML against JSON schemas make check-fact-ids # Check fact_id references against knowledge catalogs ``` `check-fact-ids` operates in two modes: - **Advisory** — when knowledge catalogs (`content/global/knowledge/*.yaml`) have no fact definitions yet: lists referenced fact_ids and exits cleanly. - **Enforcing** — when catalogs are populated: fails on any `fact_id` reference that doesn't match a canonical definition. ## Pre-commit Hooks Git hooks are stored in `.config/hooks/` (version-controlled). Activate them with: ```bash make setup # Includes hook installation make setup-hooks # Just hooks ``` Or manually: ```bash git config core.hooksPath .config/hooks ``` Active checks: | Check | Script | Behavior | |-------|--------|----------| | fact_id validation | `tooling/check-fact-ids` | Warns if catalogs are stubs; fails on unknown fact_ids when populated | The `core.hooksPath` setting uses a relative path (`.config/hooks`) that resolves per worktree, so it works correctly across all worktrees in the repository. To bypass hooks in an emergency: ```bash git commit --no-verify -m "fix: emergency hotfix" ``` ## Configuration Files The `.config/` directory holds shared configuration for linters, formatters, and CI. Examples of what goes here: - Clippy configuration overrides - gdlint/gdformat rules - CI workflow definitions (before moving to `.github/workflows/`) - Editor config templates Project-specific config that lives in subdirectories (e.g., `server/Cargo.toml`, `client/project.godot`) stays in those directories. `.config/` is for cross-cutting or shared configuration. ## Cache Directory `.cache/` is gitignored and used for: - Test result caches - Linter caches - Build artifact caches (if configured) - Coverage reports Agents and CI jobs can write freely to `.cache/` without polluting the working tree. `make clean` clears it. ## Testing Architecture (D-030) Three-layer testing strategy: 1. **Unit tests** — Inside `server/` (Rust `#[cfg(test)]`) and `client/` (gdUnit4). Test individual systems in isolation. 2. **Integration tests** — Inside `server/tests/` (Rust) and `tests/` (cross-boundary). Test system interactions, IPC serialization round-trips. 3. **Fixture-based tests** — IPC serialization fixture files in `tests/` for protocol regression testing. Known-good MessagePack payloads verified against both sides. Key components: - **CauseChain** (production ECS component) — Tracks causal attribution for testable observation sequences (D-030). - **Deterministic replay** — Server simulation is deterministic given the same seed + input sequence. Replay logs enable regression testing (#201, critical). ## SQLite Access **Never use the `sqlite3` CLI** — it crashes in Claude Code (std::bad_alloc). Use wrapper scripts: ```bash db/connectors/sqlite-query "SELECT * FROM tickets WHERE status='open'" db/connectors/sqlite-exec "UPDATE tickets SET status='done' WHERE id=1" ``` ## Qdrant / Document Search ```bash db/connectors/qdrant-search "asymmetric information design" db/connectors/qdrant-index docs/briefings/tyre.md db/connectors/qdrant-health db/connectors/qdrant-count ``` ## Decisions System Decisions are split into domain files under `decisions/` (see `decisions/README.md` for the full index). A SQLite index table syncs metadata for cross-referencing and querying. ```bash make decisions-sync # Parse decisions/*.md into SQLite make decisions-coverage # Decision-to-ticket coverage by domain make decisions-active # List all active confirmed decisions make decisions-orphan # Decisions without implementing tickets ``` The sync runs automatically as part of `make setup` and via pre-commit hook. Markdown files are the source of truth; the DB is a derived index. ## Commit Conventions See the `/commit` skill (`.claude/skills/commit/`) for full details. Summary: - Conventional commits: `type(scope): summary` - Types: `feat`, `fix`, `refactor`, `chore`, `docs`, `data`, `loc` - Scopes match project subsystems: `client`, `server`, `engine`, `simulation`, `ui`, `audio`, `meta`, etc. - Imperative mood, lowercase, no period, max 72 chars - CHANGELOG.md updated after each commit group