From 6bf908b43efe3bb22273038e3ca138a1a22efa28 Mon Sep 17 00:00:00 2001 From: Lang <7system7@gmail.com> Date: Tue, 21 Apr 2026 14:30:38 +0200 Subject: [PATCH] chg: dev: create AGENTS.md file for future maintenance #9 --- AGENTS.md | 464 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 465 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..00770bc --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,464 @@ +# AI Agent Guidelines for MineSeeker + +This document provides guidelines and context for AI coding agents working on the MineSeeker project. + +## Project Overview + +**MineSeeker** is a real-time multiplayer 1v1 minesweeper game built with Symfony (PHP) and React. Players compete to claim mines on a shared 16×16 grid, with the first to reach 26 mines winning. + +### Tech Stack + +- **Backend:** Symfony 7.2 (PHP 8.3) +- **Frontend:** React 18, Vite 6 +- **Database:** PostgreSQL 17 with materialized views +- **Storage:** MinIO (S3-compatible) +- **Real-time:** Mercure (Server-Sent Events) +- **Styling:** SCSS, MUI (Material-UI), Emotion +- **Fonts:** @fontsource packages (web), Carlito-Bold.ttf (server-side images) + +### Key Features + +**Core Gameplay:** +- **Multiplayer-focused:** 1v1 competitive gameplay where players race to claim more mines than their opponent +- **Win condition:** First player to claim 26 out of 51 mines wins +- **Real-time updates:** WebSocket-like gameplay using Mercure (Server-Sent Events) +- **Game restoration:** Players can resume unfinished games from where they left off +- **Bonus points system:** Rewards skilled play (blind hits, chain combos, edge mines, endgame mines, safe cell reveals) + +**User Features:** +- **Authentication:** Password + optional TOTP + optional WebAuthn passkeys +- **Anonymous play:** Guest players can play without creating an account +- **Profile statistics:** Detailed stats including wins, losses, draws, win rate, average score, total mines hit, and bonus points +- **Battle history:** View and replay past games move-by-move + +**Sharing & Social:** +- **Battle reports:** Shareable public pages for each completed game (`/battle/{uuid}`) +- **OG image generation:** Automatic creation of 1200×630 PNG images for social media sharing (using PHP GD) +- **Open Graph tags:** Battle share pages include rich preview cards with player names, avatars, scores, and bonus points + +--- + +## Architecture Overview + +### Backend (Symfony) + +``` +src/ +├── Controller/ # HTTP endpoints (game, profile, battle sharing) +├── Entity/ # Doctrine ORM entities +├── Repository/ # Database queries (uses QueryBuilder, not raw SQL) +├── Service/ # Business logic (BattleCardGenerator, WebAuthn, Email) +├── Dto/ # Data Transfer Objects (immutable, readonly) +├── Util/ # Game logic (TopicManager for Mercure) +└── Migrations/ # Database schema changes +``` + +**Important patterns:** +- Use Doctrine ORM QueryBuilder (not raw SQL) in repositories +- DTOs are `final readonly` classes with constructor property promotion +- Services use dependency injection via `config/services.yaml` +- Materialized views for performance (auto-refreshed via triggers) + +### Frontend (React) + +``` +assets/ +├── js/ +│ ├── mine-seeker/ # Main game bundle (self-contained) +│ │ ├── MineSeeker.jsx # Root component, wraps GameProvider + QueryClientProvider +│ │ ├── components/ # Game-specific components +│ │ │ ├── GameBoard.jsx # Main game board grid +│ │ │ ├── GameTimer.jsx # Game timer display +│ │ │ ├── BonusBox.jsx # Bonus points indicator +│ │ │ ├── BonusStatsDialog.jsx # Bonus statistics modal +│ │ │ ├── CaptchaOverlay.jsx # Captcha challenge overlay +│ │ │ ├── ChallengeCountdown.jsx # Challenge timer +│ │ │ ├── OnlinePlayersDialog.jsx # Online players list +│ │ │ ├── WaitingOverlayContent.jsx # Waiting for opponent +│ │ │ ├── grid/ # Grid-related components (cells, mines) +│ │ │ ├── profile/ # In-game profile components (PlayerColumn) +│ │ │ ├── timer/ # Timer-related components +│ │ │ └── user/ # User-related components +│ │ ├── contexts/ # React Context API +│ │ │ ├── GameContext.jsx # Game state context +│ │ │ └── GameProvider.jsx # Context provider with state logic +│ │ ├── hooks/ # Custom React hooks +│ │ │ ├── useGameDataProvider.js # React Query data provider +│ │ │ ├── useGameRefs.jsx # Refs for DOM elements +│ │ │ ├── useGameState.jsx # Game state management +│ │ │ ├── useServerCommunication.jsx # Mercure SSE connection +│ │ │ └── useStepTimer.jsx # Step-by-step timer +│ │ └── utils/ # Game-specific utilities +│ │ └── constants.jsx # Game constants, colors, defaults +│ ├── components/ # Shared UI components +│ ├── utils/ # Shared utilities +│ ├── profile.jsx # Profile page entry +│ ├── passkey.jsx # Passkey management entry +│ └── contact.jsx # Contact form entry +├── css/ +│ └── homepage/ # SCSS partials (imported by style.homepage.scss) +└── fonts/ + └── Carlito-Bold.ttf # TTF font for PHP GD image generation +``` + +**Important patterns:** +- Vite aliases: `@mine-components`, `@mine-contexts`, `@mine-hooks`, `@mine-utils`, `@global-components`, `@global-utils` +- React Query only available inside `mine-seeker` bundle +- Avoid circular dependencies (e.g., don't import from `@global-components` inside `components/` directory) +- PropTypes required on all components + +--- + +## Common Tasks + +### Adding a New Feature + +1. **Backend:** + - Create migration for schema changes + - Add/update entities and repositories + - Create DTOs for data transfer + - Add controller endpoints + - Update service configuration if needed + +2. **Frontend:** + - Create components in appropriate bundle + - Add PropTypes to all components + - Use existing hooks and utilities + - Follow styled-components pattern for MUI customization + +3. **Documentation:** + - Update relevant docs in `docs/` folder + - Add examples if introducing new patterns + +### Database Changes + +- Always create migrations: `bin/console make:migration` +- Use Doctrine QueryBuilder in repositories (not raw SQL) +- For PostgreSQL-specific features (materialized views, triggers), use raw SQL in migrations only +- Materialized views should auto-refresh via triggers + +### Styling + +- **Web fonts:** Use `@fontsource` packages (WOFF/WOFF2) +- **Server-side images:** Use TTF fonts in `assets/fonts/` (PHP GD requires TTF) +- **CSS:** Create SCSS partials in `assets/css/homepage/`, import in main file +- **Components:** Use Emotion styled-components or CSS classes + +### File Headers + +All PHP and JS/JSX files should have this header: + +```php +` +- **Formatting:** 4-space indentation, opening braces on same line for methods/classes + +**Example DTO:** + +```php +final readonly class ProfileGameDto implements JsonSerializable +{ + public function __construct( + public ?int $id, + public string $redName, + public string $blueName, + public bool $bothRegistered, + ) {} +} +``` + +### JavaScript/React + +- **Components:** Functional components with hooks +- **PropTypes:** Required on all components +- **Imports:** Use aliases (`@global-components`, `@mine-hooks`, etc.) +- **State:** Use `useState`, `useEffect`, `useCallback`, `useMemo` appropriately +- **Avoid:** Circular dependencies, especially with barrel exports + +**Example component:** + +```javascript +import React, { useState } from 'react'; +import { string, number } from 'prop-types'; + +export const MyComponent = ({ title, count }) => { + const [value, setValue] = useState(0); + + return
{title}: {count + value}
; +}; + +MyComponent.propTypes = { + title: string.isRequired, + count: number.isRequired, +}; +``` + +--- + +## Important Files & Locations + +### Configuration + +- `config/services.yaml` - Service definitions and parameters +- `vite.config.js` - Vite build config, aliases +- `.env` - Environment variables (not in git) +- `composer.json` - PHP dependencies +- `package.json` - Node dependencies + +### Key Services + +- `BattleCardGenerator` - Generates 1200×630 PNG OG images using PHP GD +- `TopicManager` - Mercure topic management and game logic +- `WebAuthnService` - Passkey authentication +- `Email services` - Various email senders in `src/Service/Email/` + +### Important Entities + +- `User` - Registered users +- `PlayedGame` - Game records with moves, grid, scores +- `RecentBattle` - Read-only entity from materialized view +- `UserStats` - Read-only entity from materialized view + +### Documentation + +- `docs/game-mechanics/BONUS_POINTS_SYSTEM.md` - Bonus points reference +- `docs/FONTS.md` - Font usage and management +- `AGENTS.md` - This file +- `CHANGELOG.md` - Project changelog + +--- + +## Common Pitfalls + +### ❌ Don't Do + +- **Don't use raw SQL in repositories** (use Doctrine QueryBuilder) +- **Don't create circular imports** (e.g., importing `@global-components` from within `components/`) +- **Don't use system fonts directly** (bundle TTF in `assets/fonts/`) +- **Don't skip PropTypes** on React components +- **Don't use `var`** in JavaScript (use `const` or `let`) +- **Don't define variables after using them** (hoisting issues with `const`) + +### ✅ Do + +- **Use Doctrine QueryBuilder** with `expr()` methods +- **Import components directly** to avoid circular dependencies +- **Bundle fonts in project** for portability +- **Add PropTypes** to all components +- **Use `const` for immutable values**, `let` for mutable +- **Define variables before using them** + +--- + +## Keeping Components in Sync + +### Battle Report Display + +The battle report/statistics appear in **two places** that must be kept synchronized: + +#### 1. BattleDialog Component (React) +**File:** `assets/js/components/BattleDialog.jsx` +- React dialog component shown on profile page +- Uses Material-UI and styled-components +- Displays game stats, bonus points, winner information + +#### 2. Battle Share Page (Twig) +**File:** `templates/Game/battle_share.html.twig` +- Public battle share page (accessible via `/battle/{uuid}`) +- Server-rendered HTML with SCSS styling +- Shows same information as BattleDialog + +### Synchronization Rules + +**When updating BattleDialog.jsx, also update battle_share.html.twig:** + +✅ Adding new stats or fields +✅ Changing display logic (winner calculation, formatting) +✅ Modifying bonus points display +✅ Updating labels or text + +**Keep in sync:** +- Game outcome logic (win/loss/draw/abandoned) +- Bonus points formatting +- Player name display +- Score display +- Stats and metadata shown + +**Example:** If you add a new stat to BattleDialog showing "fastest mine claim time", you must also add it to battle_share.html.twig so both displays show the same information. + +--- + +## Testing & Building + +### Backend + +```bash +# Run migrations +bin/console doctrine:migrations:migrate + +# Clear cache +bin/console cache:clear + +# Refresh materialized views +bin/console dbal:run-sql "REFRESH MATERIALIZED VIEW CONCURRENTLY recent_battles" +``` + +### Frontend + +```bash +# Development build with watch +npm run dev + +# Production build +npm run build + +# After changing fonts +rm -rf var/og-cache/* +``` + +--- + +## Git Workflow + +### Commit Messages + +Follow conventional commits: + +- `feat: add bonus points to battle cards` +- `fix: resolve circular dependency in BattleDialog` +- `refactor: use Doctrine QueryBuilder in RecentBattleRepository` +- `docs: add AGENTS.md for AI coding agents` +- `chore: update dependencies` + +### Creating Pull Requests + +When creating PRs, include: + +1. **Summary** - What was changed and why +2. **Changes** - List of modified files/components +3. **Testing** - How to verify the changes +4. **Screenshots** - For UI changes + +--- + +## Performance Considerations + +### Database + +- Use materialized views for expensive queries (profile stats, recent battles) +- Auto-refresh materialized views via triggers on source table changes +- Index frequently queried columns +- Use `COALESCE()` for nullable aggregates + +### Frontend + +- Lazy load large components +- Use React Query for data fetching and caching +- Avoid unnecessary re-renders (use `useMemo`, `useCallback`) +- Bundle code per entry point (profile, passkey, contact, game) + +### Images + +- Battle card images are cached in `var/og-cache/` +- Images regenerated when games change (via deterministic UUID) +- Use appropriate image sizes (1200×630 for OG images) + +--- + +## Security + +### Authentication + +- Password + TOTP (optional) + WebAuthn passkeys (optional) +- Backup codes for TOTP recovery +- Session-based authentication with `IS_AUTHENTICATED_REMEMBERED` + +### Data Access + +- Controllers check `denyAccessUnlessGranted()` +- Materialized views filter by `user_id` +- Guest players use separate `Gamer` entity (no `User` account) + +### Input Validation + +- Symfony forms for user input +- File upload validation (size, MIME type) +- WebAuthn challenge validation + +--- + +## Useful Commands + +```bash +# Symfony +bin/console debug:container ServiceName # Inspect service configuration +bin/console debug:router # List all routes +bin/console make:migration # Create new migration +bin/console doctrine:migrations:list # List migrations + +# Database +bin/console dbal:run-sql "SELECT * FROM ..." # Run SQL query + +# Assets +npm run build # Build production assets +npm run dev # Build with watch mode + +# Git +git log --oneline --graph # View commit history +git diff origin/main...HEAD # See changes since main +``` + +--- + +## Need Help? + +- **Bonus Points:** See `docs/game-mechanics/BONUS_POINTS_SYSTEM.md` +- **Fonts:** See `docs/FONTS.md` +- **Symfony Docs:** https://symfony.com/doc/current/ +- **React Docs:** https://react.dev/ +- **Doctrine ORM:** https://www.doctrine-project.org/projects/doctrine-orm/en/current/ + +--- + +## Version History + +- **2026-04-21:** Initial AGENTS.md created +- Document common patterns, pitfalls, and project structure +- Include coding standards and examples + +--- + +**Happy coding! 🚀** diff --git a/README.md b/README.md index 9feef5b..8ce8832 100644 --- a/README.md +++ b/README.md @@ -291,6 +291,7 @@ git push origin v2026.01 For detailed information about game mechanics, bonus systems, fonts, and other technical details, see the [docs](./docs/) directory: +- **[AI Agent Guidelines](./AGENTS.md)** — Comprehensive guide for AI coding agents working on this project - **[Bonus Points System](./docs/game-mechanics/BONUS_POINTS_SYSTEM.md)** — Complete reference for all bonus point types, calculation rules, and implementation details - **[Fonts](./docs/FONTS.md)** — TrueType fonts used for server-side image generation