Imported from ariesyous/li4chess (
AGENTS.md). Install upstream withnpx skills add ariesyous/li4chess. Copyright stays with the author.
Agent guide
These instructions apply throughout this repository. Start with README.md for setup and implemented capabilities, ROADMAP.md for product direction, and docs/project-state.md for accepted decisions, current work, and the next tasks. docs/rules-spec.md describes the implemented standard FFA contract and local replay boundaries.
Session continuity
- At the start of work, read the roadmap and project state, then check the working tree and relevant code. Verify handoff claims before relying on them.
- Keep durable decisions, current focus, blockers, next actions, and dated validation in
docs/project-state.md. Update it after meaningful implementation or planning changes; avoid transcript-style logs. - Track milestone status in
ROADMAP.md. Mark a milestone complete only when its exit criteria have evidence. Keep proposed choices distinct from maintainer-confirmed decisions. - Update README when implemented capabilities change, and update the rules specification alongside intentional behavior changes. Planned behavior must not be presented as implemented.
- Retain the user's scope for the current task. The roadmap provides context and sequencing; it does not authorize implementing every milestone or provisioning/deploying services in one session.
- The accepted 2026-09-08 direction is a polished local/CPU GitHub Pages checkpoint with minimal ongoing maintainer time: UI1 adds a bounded Lichess-style visual refresh with licensed asset reuse, then L1 validates and tags a release at the existing /li4chess/ project site. Cloudflare, the li4chess.org launch and hosted multiplayer are shelved, with no automatic next phase. Preserve completed local multiplayer and its evidence. Matchmaking/ratings are deferred and broader roadmap ideas are uncommitted. Keep further bot research outside this release unless needed to fix a serious defect. Handle routine engineering within scope without assigning the maintainer a comprehensive planning exercise. Use the current roadmap and task queue over historical handoffs.
Repository conventions
- Use the repository's configured human Git identity for commits. Do not substitute an AI provider's name or email as author or committer.
- Do not add AI co-author trailers, generated-by footers, or agent session links to commits or pull request descriptions.
- Keep the frozen classic bot and historical experiment artifacts intact. Label new measurements with their code version and environment; do not present historical timings as current performance.
- Validate code changes with
pnpm lint,pnpm test,pnpm build, andpnpm --filter @li4chess/web test:e2ewhen browser behavior is affected. CI runs all four. - Default CI covers the local/CPU Pages product. D1, Worker and multiplayer integration campaigns remain in the manually triggered
.github/workflows/validate-multiplayer.yml; run that workflow when changing the deferred backend or intentionally validating its shared dependencies. Those campaigns are not a default Pages merge gate.
Project structure
li4chess is a TypeScript monorepo using pnpm workspaces and Turborepo. The current product includes local four-player free-for-all chess in one browser tab, with human and CPU seats, and opt-in local authenticated private multiplayer through the maintained Worker, GuestService, GameRoom and D1. Hosted multiplayer is not activated; accounts, matchmaking and ratings remain outside the implemented scope.
apps/web: React/Vite application.src/game/useLocalGame.tsowns local game state, input handling, and CPU turn scheduling.packages/engine: pure rules engine. Keep React, browser APIs, network calls, and filesystem I/O out of this package.packages/bot: production search/evaluation, experimental search, and the frozensrc/classic/snapshot.packages/arena: seeded tournaments, replay validation, benchmarks, and result reporting.packages/protocol: validated state-v2/replay-v2, canonical SHA-256, producer provenance and strict private multiplayer wire schemas.apps/worker: default local-game Static Assets entry and explicitly configured local multiplayer routing; test-only campaign entries never deploy.packages/game-room: authenticated guest/lobby service and binding-only SQLite room authority, clocks, disconnect banks and recovery.packages/persistence: canonical D1 command/event/result history, exact receipts, fencing and replay reconstruction.packages/ui-kit: presentational board, piece glyphs, and theme. Keep game decisions in the engine or application.
Follow existing strict TypeScript and ESM conventions, including .js extensions
in relative source imports. Use workspace package exports for cross-package
dependencies. Preserve immutable state transitions and JSON-shaped game state.
Rules and game behavior
- Implement rules in
packages/engine; avoid duplicating legality or scoring in the UI or bot. - Use the shared board transforms for player-relative geometry. The board is a 14×14 array with 160 playable squares; turn order is Red → Blue → Yellow → Green, skipping inactive players.
- A legal move must leave the mover's own king safe. Resolve another player's checkmate or stalemate when rotation reaches that player, not immediately when they are checked.
- Checkmate and stalemate retain passive dead armies: zero-point capturable blockers that cannot move or attack. Their owners lose special rights and skip turns.
- Pawns automatically promote on their eighth rank to Queens with pawn provenance and one-point capture value; no underpromotion or spare king.
- Final points determine every placement, including eliminated players; equal scores share place and mean occupied rank. Third elimination ends play, with +20 per live walking King to the survivor. Claim Win is immediate. Automatic repetition, insufficient-material and 200-turn draws award each active player a flat +10 without survivor stacking.
- Resignation/timeout during the per-seat opening guard aborts; afterwards only the forfeiter's King stays live and receives recorded seeded legal moves on its regular turn. Automatic claims must secure first place even against eliminated high scorers.
applyMoveassumes a legal move. Validate external move requests against the engine's legal moves before applying them.- For intentional rules changes, update the specification and add focused regression coverage. Cover all four orientations when changing pawn movement, castling, or board transforms.
The behavior above describes li4chess-ffa-standard-v1; the historical house rules
are preserved in docs/rules-spec-house-ffa-v1.md. The accepted product
target is Chess.com's standard FFA rules. M1's compatibility audit and migration
are complete; do not restore historical house rules as a product requirement. Verify unclear
reference behavior, version the replacement specification/replays, and preserve
historical evidence rather than rewriting it to fit the new rules.
Active-king non-capture and castling ownership/rights now have accepted fixtures in all four orientations. The migration contract settles the remaining target semantics; follow its inventory without reopening decisions absent contradictory evidence. Keep rules fixes separate from bot comparisons so changes to the rules engine do not silently alter the experiment being measured.
Bot and research work
The maintainer accepted the Tetrarch advisory hybrid as the default browser CPU
on 2026-09-09. Browser turns call chooseHybrid in a dedicated Worker, with
chooseBoundedCpuMove as native fallback. li4chess remains the sole rules and
result authority. See docs/engine/tetrarch-browser-default.md for asset verification,
resource tiers and recovery. Preserve the initial audit and arena measurements
as historical evidence; they do not certify equivalent external search rules.
Each request has game/state/seat identity, shared node/time limits, termination
on cancellation and a hard watchdog. Recovery uses the current legal list.
The synchronous chooseCpuMove remains a comparison API; the laboratory's
searchPosition remains experimental. Do not mix its terminal-utility scale
with raw production evaluation. M2 calibration and acceptance evidence are in
docs/m2-acceptance.md.
- Preserve
packages/bot/src/classic/and archived evidence underdocs/engine/results/. - Both classic and production bots use the current rules engine. The laboratory utility also uses production evaluation; account for these shared dependencies in comparisons.
- Write new measurements to fresh output directories. Record the commit, any uncommitted code changes, runtime/hardware, engine configuration, seeds, and budgets alongside results.
- Arena script paths are relative to
packages/arena. Use../../arena-results/<run-name>to write into the root's ignored results directory. - Replay-validate games before drawing conclusions. Treat ply-capped games as unfinished/censored, not draws or losses.
- Distinguish tactical regression improvements, throughput measurements, and playing strength. Small comparisons and historical timings do not establish current strength or performance.
Read arena methodology, production reconciliation, and the engine recommendation before changing experiment methodology or interpreting archived results.
Development and validation
Use Node.js 24 or newer and the pnpm version pinned in package.json (10.33.0).
Run commands from the repository root:
pnpm install --frozen-lockfile
pnpm dev
pnpm lint
pnpm test
pnpm build
pnpm --filter @li4chess/web exec playwright install chromium
pnpm --filter @li4chess/web test:e2e
pnpm lint runs TypeScript checks. Unit tests use Vitest; browser tests use
Playwright and start their own Vite server. Run lint, unit tests, and build for
code changes, plus browser tests when behavior visible in the browser is affected,
including changes to the rules or bot used by the app. For documentation-only
edits, check local links, commands against package scripts, and git diff --check.
Keep Vite's /li4chess/ base path in mind when changing asset URLs or navigation:
the GitHub Pages workflow publishes apps/web/dist under that project path.
Before finishing, review the diff for unrelated changes and report what changed, which checks actually ran, and any remaining limitations. Do not report earlier test runs or historical benchmarks as fresh validation.