Files
blind_chess/CLAUDE.md
T
claude (blind_chess) 077330054b docs: table-fidelity batch deployed to both instances
Deployed 2026-05-18 to CT 690 (chess.sethpc.xyz) and chess.local
(VDJ-RIG); both verified serving the new client build. CLAUDE.md and
the handoff updated to deployed state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:09:02 -04:00

73 lines
7.3 KiB
Markdown

# blind_chess
> Web-based two-player chess where each player sees only their own pieces; the server acts as moderator.
## Start Here
**Read the latest handoff first:** `.claude/handoffs/` (most recent file).
Then check `DECISIONS.md` for settled choices, and the design specs:
- `docs/superpowers/specs/2026-04-28-blind-chess-design.md` — original MVP spec (data model, protocol, FSM, testing).
- `docs/superpowers/specs/2026-04-28-ai-player-design.md` — AI/computer player spec (Casual + gemma4 recon bots, two-phase plan).
- `docs/superpowers/specs/2026-05-18-table-fidelity-features-design.md` — table-fidelity batch (announce-all, capture tally, phantom opponent-piece layer).
## Project Identity
A digitization of a battleship-style chess variant. Two players, separated; a moderator who sees both boards and announces a fixed vocabulary of events ("Black has moved and captured", "Moving that piece will not help you", "White is in check"). The physical version requires three people; this version replaces the moderator with a server. Ships with both **vanilla** mode (full reveal — normal chess) and **blind** mode (the variation) on day one. Mode is a per-player view filter on a shared engine, not a different game.
The system's most distinctive property: highlighting in blind mode reveals **zero opponent information**. It's computed purely from `(piece type, position, own-piece set)` — a function whose signature literally cannot read opponent state. The moderator vocabulary is the only legitimate channel for opponent events.
## Current State
- **Phase:** MVP **deployed and live** at https://chess.sethpc.xyz (2026-04-28). **AI Phase 1 (Casual bot) deployed** (2026-04-28) — "Play vs computer" → Casual bot. **Blind Casual check-resolution fix shipped** (2026-04-29). **Table-fidelity feature batch deployed** (2026-05-18) — moderator announces every move/attempt to both players, a capture tally, and a client-local phantom opponent-piece layer for blind mode; live on both instances (CT 690 + `chess.local`). Client UI not yet manually browser-tested.
- **Repo:** `git.sethpc.xyz/Seth/blind_chess`.
- **Stack:** Node 22 + TypeScript, Fastify + `ws`, Svelte 5 + Vite, `chess.js`, `js-chess-engine` (Casual vanilla AI). pnpm workspace with `packages/{server,client,shared}`.
- **Deploy:** LXC **CT 690 on node-241** at 192.168.0.245, behind Caddy CT 600. Systemd unit `blind-chess.service`, port 3000. In-memory state only.
- **Tests:** 87 passing — 25 in shared (geometric + phantom-model helpers), 62 in server (FSM + view + candidates + casual brain + driver + captures + scripted-game + ai-game-casual integration). The client package has no test harness by design.
- **Known gaps (deferred):** drag-and-drop for *real* moves (still click-to-move; the phantom layer added pointer-drag for phantom pieces only), full integration coverage of every endgame path, mobile-specific polish, observability beyond `/api/health` and `[bot resign]` (no metrics, no per-game tracing), `localStorage` cleanup for phantom layers of abandoned games.
- **AI Phase 2 (gemma4 recon, not built):** Spec in `docs/superpowers/specs/2026-04-28-ai-player-design.md`. Will reuse the Phase 1 `Brain`/`BotDriver` infrastructure. Plan to be written when Phase 1 has soaked. Bots play through the same view filter and FSM as humans — no oracle access.
## Key files
- `IDEA.md` — original project brief (Seth's words)
- `DECISIONS.md` — locked architectural and gameplay decisions
- `docs/superpowers/specs/2026-04-28-blind-chess-design.md` — full design spec (data model, protocol, FSM, testing)
- `docs/superpowers/specs/2026-04-28-ai-player-design.md` — AI/computer player spec (Casual + gemma4 recon, two-phase plan, endpoint priority list, acceptance bars)
- `packages/shared/src/geometric.ts` — the zero-leak helper. The signature is the proof.
- `packages/server/src/view.ts``buildView`, the security boundary.
- `packages/server/src/commit.ts` — touch-move FSM (the spec's hierarchy decision table).
- `packages/server/src/translator.ts` — chess.js `Move` → moderator-vocabulary enum.
- `packages/server/src/captures.ts``captureTally`, the per-viewer capture-count derivation (Feature 2).
- `packages/server/src/game-end.ts` — shared `endGame` / `finalizeIfEnded` helpers used by both ws and bot driver.
- `packages/server/src/bot/` — Brain interface, BotDriver, CasualBrain, candidates. Vanilla mode delegates to `js-chess-engine` at level 2; blind mode uses a heuristic.
- `packages/client/src/lib/stores/phantoms.svelte.ts` — client-LOCAL phantom opponent-piece store (Feature 3). Never sent to the server; `phantom-drag.svelte.ts` is its pointer-drag controller.
- `scripts/selfplay.ts` — operator CLI for evaluating Casual vs Casual / Random self-play. `pnpm selfplay --help`.
- `deploy/blind-chess.service` — systemd unit (canonical at `/etc/systemd/system/blind-chess.service` on the CT).
- `deploy/Caddyfile.snippet` — block already added to `/etc/caddy/Caddyfile` on CT 600.
## Operations
- **Logs:** `ssh root@192.168.0.245 'journalctl -u blind-chess -f'`
- **Restart:** `ssh root@192.168.0.245 'systemctl restart blind-chess'`
- **Health:** `curl https://chess.sethpc.xyz/api/health`
- **Deploy update:** `pnpm -r build``pnpm --filter @blind-chess/server deploy --prod --legacy .deploy-server` → rsync server bundle to `/opt/blind-chess/server/` and client `dist/` to `/opt/blind-chess/client/dist/``chown -R blindchess:blindchess /opt/blind-chess``systemctl restart blind-chess`. Server restart drops in-memory games (acceptable for MVP).
### Local instance — `chess.local` on VDJ-RIG
A second, **LAN-only** deploy on VDJ-RIG (192.168.0.143), fully independent of the CT 690 / chess.sethpc.xyz instance (separate in-memory state). Serves on **port 80**, reached at `http://chess.local` via an mDNS alias — no Caddy, no TLS.
- **Artifacts** (`deploy/`): `blind-chess-local.service` (server unit; binds port 80 as the non-root `blindchess` user via `CAP_NET_BIND_SERVICE`), `chess-mdns-alias` + `chess-mdns-alias.service` (publishes the `chess.local` mDNS name with `avahi-publish -a -R``-R` avoids a reverse-PTR collision with the host's own `.local` name), `install-local.sh` (root-side installer).
- **On the rig:** tree at `/opt/blind-chess/{server,client/dist}`, units `blind-chess.service` + `chess-mdns-alias.service`, Node 22 via NodeSource.
- **Logs:** `ssh vdj-rig 'journalctl -u blind-chess -f'`
- **Restart:** `ssh vdj-rig 'sudo systemctl restart blind-chess'`
- **Health:** `curl http://chess.local/api/health`
- **Redeploy:** on steel141 `pnpm -r build` + `pnpm --filter @blind-chess/server deploy --prod --legacy .deploy-server`; rsync `.deploy-server/` → rig `~/blind-chess-stage/server/`, `packages/client/dist/``~/blind-chess-stage/client-dist/`, and the `deploy/` files → `~/blind-chess-stage/`; then `sudo bash ~/blind-chess-stage/install-local.sh`.
## Conventions
- Inherits global homelab conventions from `~/bin/CLAUDE.md` (gitea CLI, conventional commits, `.claude/handoffs/` for session state).
- pnpm workspace; do not use npm/yarn lockfiles.
- All inter-package types live in `packages/shared/`. Never duplicate protocol types in client or server.
- Server is the single authority on game state. Client `commit` messages are requests, not facts.
- The view filter (`buildView`) is the only egress for board state. Don't bypass it.