Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.venv/
plugins/*/.venv/
*.egg-info/
.pytest_cache/
.coverage
htmlcov/
dist/
build/

# Node
frontend/node_modules/
frontend/dist/
frontend/.parcel-cache/

# IDE
.idea/
.vscode/
*.swp
*.swo

# Git
.git/
.gitignore

# Docs (tests included for container testing)
*.md
!README.md

# Logs and temp files
*.log
*.tmp
167 changes: 81 additions & 86 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,132 +2,127 @@

Instructions for Claude Code when working on this project.

## Python Environment
## Docker Development

This project uses a virtual environment at `.venv/`. Always use it:
This project uses Docker Compose to run the backend and plugins. Frontend runs separately via npm.

```bash
# Run Python commands through the venv
.venv/Scripts/python -m pytest tests/ -v
.venv/Scripts/pip install -e ".[dev]"

# Or activate first (Windows)
.venv\Scripts\activate

# Or activate first (Unix)
source .venv/bin/activate
```

**NEVER** use system Python or `pip install` directly. Always use `.venv/Scripts/pip`.

Important: use correct slashes - usually "/" is the right one.
### Starting the Backend

## Dependency Management

### Python (Backend)

Dependencies are defined in `pyproject.toml`:
- Runtime deps in `[project.dependencies]`
- Dev deps in `[project.optional-dependencies.dev]`
```bash
# Build all images (first time or after code changes)
docker compose build

To add a new dependency:
1. Add it to `pyproject.toml` first
2. Then install: `.venv/Scripts/pip install -e ".[dev]"`
# Start all services
docker compose up

**NEVER** run `pip install <package>` directly without adding to pyproject.toml first.
# Start in background
docker compose up -d

### JavaScript (Frontend)
# View logs
docker compose logs -f app

Dependencies are defined in `frontend/package.json`.
# Stop all services
docker compose down
```

To add a new dependency:
1. Add it to `package.json` under `dependencies` or `devDependencies`
2. Use `"latest"` if unsure of version, then lock to resolved version
3. Run `npm install` from the `frontend/` directory
### Starting the Frontend

**NEVER** run `npm install <package>` directly without adding to package.json first.
```bash
cd frontend
npm install # first time only
npm run dev # starts dev server on http://localhost:5173
```

## Running Tests
### Rebuilding After Changes

```bash
# Main app tests (140 pass, 0 skipped)
.venv/Scripts/python -m pytest tests/ -v --tb=short --ignore=tests/integration
# Rebuild specific service
docker compose build gambit && docker compose up -d gambit

# Gambit plugin tests (76 tests, run from plugin venv)
plugins/gambit/.venv/Scripts/python -m pytest plugins/gambit/tests/ -v
# Rebuild all services
docker compose build && docker compose up -d
```

# PyCID plugin tests (run from plugin venv)
plugins/pycid/.venv/Scripts/python -m pytest plugins/pycid/tests/ -v
### Running Tests

# Integration tests (requires plugin venvs; plugins start automatically)
.venv/Scripts/python -m pytest tests/integration/ -v --tb=short
```bash
# Run main app tests inside container
docker compose exec app pytest tests/ -v --tb=short --ignore=tests/integration

# All test suites (Windows)
scripts/run-all-tests.ps1
# Run integration tests (requires all services running)
docker compose exec app pytest tests/integration/ -v --tb=short

# Frontend build (includes TypeScript check)
cd frontend && npm run build
```

Tests for pygambit-dependent analysis (Nash, IESDS, profile verification, EFG/NFG
parsing) live in `plugins/gambit/tests/` and run in the gambit plugin venv.
Integration tests in `tests/integration/` verify the full main app → plugin HTTP flow.

## Plugin Architecture

Analysis plugins (Gambit, PyCID) run as isolated FastAPI subprocesses, each in its
own virtual environment. This avoids dependency conflicts (e.g. PyCID needs
`pgmpy==0.1.17` + `pygambit>=16.3.2`, while Gambit analyses use `pygambit==16.5.0`).

### Setting Up Plugin Venvs

```bash
# Windows
scripts/setup-plugins.ps1

# Unix
scripts/setup-plugins.sh
```

This creates `plugins/gambit/.venv/` and `plugins/pycid/.venv/` with their respective
dependencies. Plugin venvs are gitignored.
Analysis plugins (Gambit, PyCID, Vegas, EGTTools, OpenSpiel) run as Docker containers
managed by Docker Compose. This avoids dependency conflicts (e.g., PyCID needs
`pgmpy==0.1.17` + `pygambit>=16.3.2`, while Gambit analyses use `pygambit`).

### How It Works

- `plugins.toml` defines plugin subprocess commands, working directories, and restart policies
- On app startup, `PluginManager` launches each plugin on a dynamic port via `subprocess.Popen`
- `docker-compose.yml` defines all services and their health checks
- `plugins.toml` lists plugin names; URLs come from environment variables
- On app startup, `PluginManager` health-checks each plugin container
- Each plugin exposes `GET /health`, `GET /info`, `POST /analyze`, `POST /parse/{format}`, `GET /tasks/{id}`, `POST /cancel/{id}`
- `RemotePlugin` adapter makes HTTP plugins look like local `AnalysisPlugin` instances
- Plugins that advertise format support (e.g. `.efg`, `.nfg`) get registered as format parsers via `app/formats/remote.py`
- If a plugin isn't running, its analyses and formats are unavailable (graceful degradation)
- Plugins that advertise format support (e.g., `.efg`, `.nfg`) get registered as format parsers
- If a plugin container isn't healthy, its analyses and formats are unavailable (graceful degradation)

### Plugin HTTP Contract

See `plugins.toml` for configuration. Each plugin is a FastAPI app implementing API v1.
Each plugin is a FastAPI app implementing API v1. See individual plugin Dockerfiles in `docker/`.

## Starting the App
### Service Ports

```bash
# Backend (plugins start automatically if venvs are set up)
.venv/Scripts/python -m uvicorn app.main:app --reload
| Service | Internal Port | External Port |
|------------|---------------|---------------|
| Main App | 8000 | 8000 |
| Gambit | 5001 | 5001 |
| PyCID | 5002 | 5002 |
| EGTTools | 5003 | 5003 |
| Vegas | 5004 | 5004 |
| OpenSpiel | 5005 | 5005 |

# Frontend dev server
cd frontend && npm run dev
```
## Dependency Management

### Python (Backend)

Dependencies are defined in `pyproject.toml` and plugin-specific `pyproject.toml` files.
Docker images install dependencies during build.

To add a new dependency:
1. Add it to the appropriate `pyproject.toml`
2. Rebuild the Docker image: `docker compose build <service>`

### JavaScript (Frontend)

Dependencies are defined in `frontend/package.json`.

To add a new dependency:
1. Add it to `package.json` under `dependencies` or `devDependencies`
2. Run `npm install` from the `frontend/` directory

## Project Structure

- `app/` - FastAPI backend (thin orchestrator)
- `app/formats/` - Format registry and JSON parser; gambit formats registered dynamically from plugin
- `app/formats/remote.py` - Proxy format parsing to remote plugins via HTTP
- `app/plugins/` - Local plugins (validation, dominance) no external deps
- `app/core/plugin_manager.py` - Subprocess supervisor for remote plugins
- `app/plugins/` - Local plugins (validation, dominance) - no external deps
- `app/core/plugin_manager.py` - Plugin discovery and health-checking for Docker containers
- `app/core/remote_plugin.py` - HTTP adapter for remote plugins
- `plugins/gambit/` - Gambit plugin service (pygambit, own venv)
- `plugins/pycid/` - PyCID plugin service (pycid, pgmpy, own venv)
- `plugins.toml` - Plugin configuration
- `plugins/gambit/` - Gambit plugin service (pygambit)
- `plugins/pycid/` - PyCID plugin service (pycid, pgmpy)
- `plugins/vegas/` - Vegas DSL plugin service
- `plugins/egttools/` - Evolutionary game theory plugin service
- `plugins/openspiel/` - OpenSpiel plugin service (CFR, exploitability)
- `docker/` - Dockerfiles for all services
- `docker-compose.yml` - Service orchestration
- `plugins.toml` - Plugin configuration (names only; URLs from environment)
- `frontend/` - React + Pixi.js frontend
- `tests/` - Python tests (main app, 140 tests)
- `tests/integration/` - Integration tests (main app + plugins, 8 tests)
- `tests/` - Python tests (main app)
- `tests/integration/` - Integration tests (main app + plugins)
- `examples/` - Sample game files (.efg, .nfg, .json)
- `scripts/` - Setup and utility scripts
68 changes: 38 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,27 @@ A canvas-first game theory analysis and visualization workbench. Build, visualiz

### Prerequisites

- Python 3.12+
- Node.js 18+
- Rust (for building pygambit)
- Docker and Docker Compose
- Node.js 18+ (for frontend development)

### Backend Setup
### Backend Setup (Docker)

```bash
# Create and activate virtual environment
py -3.12 -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # Unix
# Build all images (first time or after code changes)
docker compose build

# Install dependencies
pip install -e ".[dev]"
# Start all services
docker compose up -d

# Set up analysis plugins (Nash equilibrium, IESDS)
scripts/setup-plugins.ps1 # Windows
# scripts/setup-plugins.sh # Unix
# View logs
docker compose logs -f app

# Start the server
uvicorn app.main:app --reload
# Stop all services
docker compose down
```

The backend API will be available at http://localhost:8000.

### Frontend Setup

```bash
Expand All @@ -57,20 +55,21 @@ thrones/
│ ├── models/ # Game data models
│ ├── plugins/ # Local analysis plugins
│ └── core/ # Store, registry, task manager
├── plugins/ # Remote analysis plugins (isolated venvs)
├── plugins/ # Remote analysis plugins (Docker containers)
│ ├── gambit/ # Nash, IESDS, EFG/NFG parsing (pygambit)
│ ├── pycid/ # MAID Nash, strategic relevance (pycid)
│ ├── vegas/ # Vegas DSL parsing (.vg files)
│ ├── egttools/ # Evolutionary dynamics (replicator, fixation)
│ └── openspiel/ # CFR, exploitability (Linux/macOS only)
│ └── openspiel/ # CFR, exploitability
├── docker/ # Dockerfiles for all services
├── docker-compose.yml # Service orchestration
├── frontend/ # React + Pixi.js UI
│ └── src/
│ ├── canvas/ # Game visualization
│ ├── components/ # UI components
│ └── stores/ # State management
├── examples/ # Sample game files
├── tests/ # Test suites
└── docs/ # Documentation
└── tests/ # Test suites
```

## Documentation
Expand All @@ -87,14 +86,11 @@ thrones/
## Running Tests

```bash
# Backend tests
.venv/Scripts/python -m pytest tests/ -v --ignore=tests/integration

# Plugin tests (run from plugin venv)
plugins/gambit/.venv/Scripts/python -m pytest plugins/gambit/tests/ -v
# Run main app tests inside container
docker compose exec app pytest tests/ -v --tb=short --ignore=tests/integration

# Integration tests
.venv/Scripts/python -m pytest tests/integration/ -v
# Run integration tests (requires all services running)
docker compose exec app pytest tests/integration/ -v --tb=short

# Frontend build (includes TypeScript check)
cd frontend && npm run build
Expand All @@ -119,18 +115,30 @@ The `examples/` directory contains sample games in various formats:

## Technology Stack

- **Backend**: FastAPI, Pydantic
- **Backend**: FastAPI, Pydantic, Docker Compose
- **Frontend**: React 19, Pixi.js 8, Zustand, TypeScript
- **Analysis Plugins**:
- **Analysis Plugins** (Docker containers):
- **Gambit**: Nash equilibrium, IESDS, EFG/NFG parsing (pygambit)
- **PyCID**: MAID Nash equilibrium, strategic relevance analysis (pycid)
- **Vegas**: Vegas DSL game description language
- **EGTTools**: Evolutionary dynamics, replicator equations, fixation probabilities
- **OpenSpiel**: CFR, exploitability (Linux/macOS only)
- **OpenSpiel**: CFR, exploitability

## Service Ports

| Service | Port |
|------------|------|
| Main App | 8000 |
| Gambit | 5001 |
| PyCID | 5002 |
| EGTTools | 5003 |
| Vegas | 5004 |
| OpenSpiel | 5005 |
| Frontend | 5173 |

## Current Version

**v0.5.0** - Plugin ecosystem with 5 remote analysis plugins.
**v0.5.0** - Plugin ecosystem with 5 remote analysis plugins running as Docker containers.

## License

Expand Down
Loading