Files
sigra/AGENTS.md

4.9 KiB

AGENTS.md - Guidelines for Agentic Coding

Project Overview

This is a Flask web application - a "Jeopardy-style" quiz game about the Russian short story "Уроки французского" by Valentin Rasputin.

Tech Stack:

  • Backend: Python 3.13 with Flask
  • Frontend: HTML, CSS, JavaScript (vanilla)
  • Data Storage: JSON file (data/questions.json)
  • State: Browser localStorage (client-side)
  • Container: Docker

Build/Test Commands

Running Locally (without Docker)

# Activate virtual environment
source venv/bin/activate

# Run Flask app (default port 5000)
python src/app.py

# Run on specific port
python -c "from src.app import app; app.run(port=5002)"

Running with Docker

# Build image
./build.sh

# Run container
./run.sh

# Stop container
docker stop sigra && docker rm sigra

Note: Dockerfile copies only src/ directory into the container (app.py, data/, templates/, static/).

Manual Testing

This project does not have a formal test suite. For manual testing:

Code Style Guidelines

Python (app.py)

Imports - Standard library first, then third-party:

import json
from flask import Flask, render_template, request, redirect, url_for, make_response

Formatting

  • Use 4 spaces for indentation
  • Maximum line length: 100 characters
  • Blank lines: 2 between top-level definitions, 1 between function definitions

Naming Conventions

  • snake_case for variables, functions
  • PascalCase for classes
  • UPPER_SNAKE_CASE for constants

Error Handling

  • Use try/except for file operations (JSON loading/saving)
  • Return proper HTTP error codes (400, 404, 500)
  • Log errors to console

Flask-Specific

  • Use app.secret_key for sessions
  • Always use ensure_ascii=False with JSON for Cyrillic support
  • Use context_processor for global template variables

JavaScript (templates/*.html)

General

  • Use vanilla JavaScript (no frameworks)
  • Prefer var over let/const for compatibility
  • Use function keyword instead of arrow functions

Event Handling

  • Use onclick directly in HTML or element.onclick = function()
  • Avoid addEventListener for simplicity

DOM Manipulation

  • Use document.getElementById and document.querySelector
  • Template literals for dynamic content
  • Use JSON.parse() and JSON.stringify() for localStorage

Naming - camelCase for variables and functions

HTML/CSS (templates/*.html)

Template Syntax (Jinja2)

  • Use {% for %} loops with enumerate() for indexed iteration
  • Pass data via {{ variable }} syntax
  • Use |tojson filter for JavaScript data

CSS

  • Use CSS custom properties (variables) for colors
  • Follow BEM-like naming for classes
  • Keep responsive design in mind

Structure

  • Inline CSS in <style> tags
  • Inline JS in <script> tags at end of body

File Organization

/home/eof/dev/roma/sigra/
├── Dockerfile             # Docker image definition
├── build.sh               # Build script
├── run.sh                 # Run script
├── .dockerignore          # Docker ignore
├── src/                   # Application source (copied to container)
│   ├── app.py             # Flask application
│   ├── data/
│   │   └── questions.json # Game questions
│   ├── templates/        # Jinja2 templates
│   └── static/           # Static assets
├── helm/                  # Kubernetes Helm chart
├── venv/                  # Virtual environment
├── SPEC.md               # Project specification
├── AGENTS.md            # This file
└── .gitignore           # Git ignore rules

Common Patterns

Adding a New Question

  1. Edit data/questions.json manually or via admin panel at /admin
  2. Structure:
    {
        "cost": 600,
        "question": "Question text?",
        "options": ["Option 1", "Option 2", "Option 3", "Option 4"],
        "answer": 0
    }
    

Adding a New Route

  1. Add route in app.py using @app.route()
  2. Return render_template() or jsonify()

Game State (localStorage)

  • Key: francuzskiy_game
  • Structure: { score: 0, answered: [], userAnswers: {}, teams: [] }
  • answered: array of "cat_q" keys (e.g., ["0_0", "1_2"])
  • userAnswers: object with keys and {team, answer} values

Multi-team Support

  • Teams: 1-3 teams supported
  • Questions: 30 (always, regardless of team count)
  • Auto-switch to next team after answering

Security Notes

  • Admin panel password: stored in app.py (ADMIN_PASSWORD)
  • No database - data in JSON file
  • No SQL injection risk
  • XSS: user input in questions is trusted (admin-only)

Dependencies

Flask==3.1.3
Jinja2==3.1.6
Werkzeug==3.1.6

Git Conventions

  • Do NOT commit without explicit user request
  • Run lint/typecheck before committing if available
  • Keep commits focused and descriptive