From 57633addfe1ef2ecbcd8ab367fcb688868e9b2c9 Mon Sep 17 00:00:00 2001 From: francy51 Date: Tue, 16 Jun 2026 11:49:13 -0400 Subject: [PATCH] chore: sync codebase remediation, gameplay systems, and docs Security & infrastructure: - Remove unused services/ (auth, spacetimedb) and auth.db - Add .env.example template, expand .gitignore for env/db files - Add GitHub Actions CI + commitlint config and workflows - Add manual vendor chunking and source maps to docs/site vite configs Shared UI & docs app: - Add ARIA props and focus-visible rings to Button/Panel - Add ButtonAsLink primitive; use shared Button in NotFound - Wire @void-nav/ui into docs app; refresh content pages - Replace Todo page with Kanban board Gameplay (Bevy): - Add ai module (behavior, faction, navigation, perception, spawning, states) - Add narrative module (events, history, synthesis, ui) - Refine galaxy contents and in-system flight/scene systems --- .env.example | 35 + .github/workflows/ci.yml | 113 +++ .github/workflows/commitlint.yml | 18 + .gitignore | 22 +- AGENTS.md | 17 +- CLAUDE.md | 146 +++ IMPLEMENTATION_SUMMARY.md | 310 ++++++ README.md | 56 +- apps/docs/package.json | 1 + apps/docs/src/App.tsx | 4 +- apps/docs/src/components/NotFound.tsx | 4 +- apps/docs/src/data/nav.ts | 2 +- apps/docs/src/pages/docs/ArchitecturePage.tsx | 506 ++------- apps/docs/src/pages/docs/BackendPage.tsx | 6 +- apps/docs/src/pages/docs/KanbanBoardPage.tsx | 958 ++++++++++++++++++ apps/docs/src/pages/docs/OverviewPage.tsx | 130 ++- apps/docs/src/pages/docs/RoadmapPage.tsx | 172 +--- apps/docs/src/pages/docs/TechStackPage.tsx | 41 +- apps/docs/src/pages/docs/TodoPage.tsx | 922 ----------------- apps/docs/vite.config.ts | 21 + apps/game/src/camera.rs | 11 +- apps/game/src/gameplay/ai/behavior.rs | 355 +++++++ apps/game/src/gameplay/ai/faction.rs | 115 +++ apps/game/src/gameplay/ai/mod.rs | 87 ++ apps/game/src/gameplay/ai/navigation.rs | 120 +++ apps/game/src/gameplay/ai/perception.rs | 162 +++ apps/game/src/gameplay/ai/spawning.rs | 311 ++++++ apps/game/src/gameplay/ai/states.rs | 207 ++++ apps/game/src/gameplay/galaxy/contents.rs | 67 +- apps/game/src/gameplay/galaxy/mod.rs | 31 +- apps/game/src/gameplay/in_system/flight.rs | 35 +- apps/game/src/gameplay/in_system/mod.rs | 15 +- apps/game/src/gameplay/in_system/scene.rs | 39 + apps/game/src/gameplay/mod.rs | 2 + apps/game/src/gameplay/narrative/events.rs | 212 ++++ apps/game/src/gameplay/narrative/history.rs | 313 ++++++ apps/game/src/gameplay/narrative/mod.rs | 70 ++ apps/game/src/gameplay/narrative/synthesis.rs | 51 + apps/game/src/gameplay/narrative/ui.rs | 64 ++ apps/game/src/gameplay/starting_base/scene.rs | 1 + apps/game/src/main.rs | 8 +- apps/site/vite.config.ts | 19 + commitlint.config.js | 35 + package.json | 7 +- packages/ui/package.json | 3 +- packages/ui/src/index.ts | 1 + packages/ui/src/primitives/Button.tsx | 66 +- packages/ui/src/primitives/ButtonAsLink.tsx | 49 + packages/ui/src/primitives/Panel.tsx | 38 +- pnpm-lock.yaml | 735 +++++++++++++- services/AGENTS.md | 12 - services/auth/auth.db | Bin 131072 -> 0 bytes services/auth/package.json | 24 - services/auth/src/auth.ts | 38 - services/auth/src/index.ts | 53 - services/auth/tsconfig.json | 7 - services/spacetimedb/AGENTS.md | 67 -- services/spacetimedb/package.json | 12 - services/spacetimedb/src/index.ts | 623 ------------ services/spacetimedb/tsconfig.json | 8 - 60 files changed, 5084 insertions(+), 2473 deletions(-) create mode 100644 .env.example create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/commitlint.yml create mode 100644 CLAUDE.md create mode 100644 IMPLEMENTATION_SUMMARY.md create mode 100644 apps/docs/src/pages/docs/KanbanBoardPage.tsx delete mode 100644 apps/docs/src/pages/docs/TodoPage.tsx create mode 100644 apps/game/src/gameplay/ai/behavior.rs create mode 100644 apps/game/src/gameplay/ai/faction.rs create mode 100644 apps/game/src/gameplay/ai/mod.rs create mode 100644 apps/game/src/gameplay/ai/navigation.rs create mode 100644 apps/game/src/gameplay/ai/perception.rs create mode 100644 apps/game/src/gameplay/ai/spawning.rs create mode 100644 apps/game/src/gameplay/ai/states.rs create mode 100644 apps/game/src/gameplay/narrative/events.rs create mode 100644 apps/game/src/gameplay/narrative/history.rs create mode 100644 apps/game/src/gameplay/narrative/mod.rs create mode 100644 apps/game/src/gameplay/narrative/synthesis.rs create mode 100644 apps/game/src/gameplay/narrative/ui.rs create mode 100644 commitlint.config.js create mode 100644 packages/ui/src/primitives/ButtonAsLink.tsx delete mode 100644 services/AGENTS.md delete mode 100644 services/auth/auth.db delete mode 100644 services/auth/package.json delete mode 100644 services/auth/src/auth.ts delete mode 100644 services/auth/src/index.ts delete mode 100644 services/auth/tsconfig.json delete mode 100644 services/spacetimedb/AGENTS.md delete mode 100644 services/spacetimedb/package.json delete mode 100644 services/spacetimedb/src/index.ts delete mode 100644 services/spacetimedb/tsconfig.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5c2459b --- /dev/null +++ b/.env.example @@ -0,0 +1,35 @@ +# Space-Game Environment Configuration Example +# Copy this file to .env.local and fill in your actual values +# NEVER commit .env.local to version control + +# ============================================================================== +# SpacetimeDB Configuration +# ============================================================================== +# Primary variables (used by Rust backend) +SPACETIMEDB_DB_NAME=void-nav-dev +SPACETIMEDB_HOST=http://127.0.0.1:3000 + +# Frontend variables (Vite apps) +VITE_SPACETIMEDB_DB_NAME=void-nav-dev +VITE_SPACETIMEDB_HOST=http://127.0.0.1:3000 + +# ============================================================================== +# Better Auth Configuration +# ============================================================================== +# Generate a secure random secret for production: +# openssl rand -base64 32 +BETTER_AUTH_SECRET=your-secret-here-generate-with-openssl-rand-base64-32 +BETTER_AUTH_URL=http://localhost:4000 + +# ============================================================================== +# Application URLs +# ============================================================================== +VITE_DOCS_URL=http://localhost:5173/docs +VITE_GAME_URL=http://localhost:5175 + +# ============================================================================== +# CORS Configuration (for auth service) +# ============================================================================== +# Comma-separated list of allowed origins for CORS +# Example: CORS_ALLOWED_ORIGINS=https://docs.example.com,https://site.example.com +CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:5174,http://localhost:5175 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7f39382 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,113 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + # TypeScript type checking and build + typescript-check: + name: TypeScript Check + runs-on: ubuntu-latest + strategy: + matrix: + app: [docs, site] + steps: + - uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + cache: "pnpm" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Type check ${{ matrix.app }} + working-directory: apps/${{ matrix.app }} + run: pnpm check + + - name: Build ${{ matrix.app }} + working-directory: apps/${{ matrix.app }} + run: pnpm build + + # Rust tests and formatting check + rust-check: + name: Rust Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo build + uses: actions/cache@v4 + with: + path: apps/game/target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Check formatting + working-directory: apps/game + run: cargo fmt -- --check + + - name: Run Clippy + working-directory: apps/game + run: cargo clippy -- -D warnings + + - name: Run tests + working-directory: apps/game + run: cargo test + + # Security audit for dependencies + security-audit: + name: Security Audit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + cache: "pnpm" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run npm audit + run: pnpm audit --audit-level moderate + + - name: Check for leaked secrets + uses: trufflesecurity/trufflehog@main + with: + path: ./ + base: ${{ github.event.repository.default_branch }} + head: HEAD diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 0000000..3c093e0 --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,18 @@ +name: Commit Lint + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + commitlint: + name: Lint Commit Messages + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: wagoid/commitlint-github-action@v6 + with: + configFile: .commitlint.config.js diff --git a/.gitignore b/.gitignore index cac5382..38443a1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,13 +8,33 @@ coverage/ .parcel-cache/ .cache/ .DS_Store + +# Environment files (never commit these) .env .env.local .env.*.local + +# SpacetimeDB spacetime.local.json +.spacetime-dev/ + +# TypeScript *.tsbuildinfo vite.config.js vite.config.d.ts + +# Playwright .playwright-mcp/ -.spacetime-dev/ + +# Rust target/ + +# Database files (SQLite, SpacetimeDB, etc.) +*.db +*.db-shm +*.db-wal +*.sqlite +*.sqlite3 + +# CI/CD local testing +.github/workflows/.local* diff --git a/AGENTS.md b/AGENTS.md index e2a4ed8..e0ea3e3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # VOID::NAV — Monorepo Root -Single-player open-world space exploration RPG. Windward Horizon in space with FTL-style combat. +Single-player narrative-driven space exploration saga. Windward meets Stellaris with AI-generated storytelling in the style of The Templin Institute. ## Directory Map @@ -10,29 +10,26 @@ Single-player open-world space exploration RPG. Windward Horizon in space with F | `apps/game` | Playable game client — **Rust + Bevy** (independent of the JS/TS workspace) | | `apps/site` | Public landing page (Vite + React) | | `packages/ui` | Shared UI primitives and design tokens for the TS apps | -| `services/spacetimedb` | SpacetimeDB TypeScript backend module (authoritative game state) | | `scripts/` | Dev tooling (dev.sh startup script) | | `archive/` | Legacy pre-monorepo files kept for reference | ## Key Files -- `package.json` — pnpm workspace scripts (`dev`, `build`, `check`, `generate:bindings`) +- `package.json` — pnpm workspace scripts (`dev`, `build`, `check`) - `pnpm-workspace.yaml` — workspace glob patterns (covers TS apps only) -- `spacetime.json` — SpacetimeDB module path and binding generation config - `tsconfig.base.json` — Shared TypeScript config (ES2020, React JSX) — does not apply to `apps/game` - `apps/game/Cargo.toml` — Rust manifest for the game binary ## Commands -### JS/TS workspace (docs, site, packages/ui, services) +### JS/TS workspace (docs, site, packages/ui) ```bash -pnpm dev # Full stack: SpacetimeDB + docs/site +pnpm dev # Docs + site servers pnpm dev:docs # Docs only (port 5173) pnpm dev:site # Site only (port 5174) pnpm build # Build all TS packages pnpm check # Typecheck all TS packages -pnpm generate:bindings # Regenerate SpacetimeDB TypeScript bindings ``` ### Rust game (`apps/game`) @@ -47,13 +44,11 @@ cargo clippy # Lint ## Architecture Notes -- **Two independent toolchains coexist**: the pnpm/TS workspace (docs, site, UI lib, SpacetimeDB backend) and the Cargo/Rust game client. They share no code. -- **SpacetimeDB** remains the authoritative persistence layer. The game client will connect to it via the SpacetimeDB Rust SDK when wired up (TS bindings generated by `pnpm generate:bindings` are consumed by the docs prototype, not the game). +- **Two independent toolchains coexist**: the pnpm/TS workspace (docs, site, UI lib) and the Cargo/Rust game client. They share no code. +- **V1 is single-player** with local persistence. Future multiplayer servers will be added as an optional enhancement. - **Naming follows RFC 344**: see `apps/game/AGENTS.md` for Rust/Bevy conventions. ## Conventions (TS apps) -- SpacetimeDB is the persistence layer from day 1 — no localStorage for game state in the docs prototype - TS apps use Tailwind CSS v4 with custom design tokens from `packages/ui` - 3D rendering in `apps/docs` uses React Three Fiber + Drei + Three.js -- Module bindings are auto-generated — never edit generated bindings by hand diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..e9fd522 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,146 @@ +# VOID::NAV - AI Agent Guidelines + +## Project Overview + +VOID::NAV is a single-player narrative-driven space exploration game built with: +- **Rust + Bevy 0.16** for the game client (`apps/game/`) +- **TypeScript + React** for docs and site (`apps/docs/`, `apps/site/`) +- **pnpm workspace** monorepo structure + +## Key Technical Patterns + +### Bevy ECS Architecture +- The game uses Bevy's Entity Component System with state-based gameplay +- States: MainMenu, Galaxy, CharacterCreation, StartingBaseSelection, InGame, Options +- Systems use `run_if(in_state(AppState::InGame))` for state-gated execution +- Components are organized by feature module (ai, movement, galaxy, narrative, etc.) + +### Time API (Bevy 0.16) +- Use `time.delta_secs()` NOT `time.delta_seconds()` for delta time +- Time is accessed as `Res