No description
Find a file
lila 5ee594334c flooring sense difficulty instead of rejecting the entry
Every rejection in the German run was the same rule: a translation ranked
below its own sense. The model tags a sense "medium" while correctly
tagging some translations "easy" — the translations are right and the
derived sense label is wrong, but the whole entry was discarded.

The prompt defines sense difficulty as the easiest translation difficulty
in that sense, so it is a derived value rather than an independent
judgement. validate.ts now recomputes it via applySenseDifficultyFloor.

The floor only ever lowers. Raising a sense to match its translations
would gate a concept out of levels it belongs in and collapse the
concept-vs-word distinction the two difficulty columns exist to express
(design-doc section 4).

- validate.ts: drop the cross-field rejection, add the floor; the valid
  result now carries "normalizations" so repairs are reported, not silent
- pipeline.ts: count and print normalizations per batch and in the summary
- replay.ts: new, re-validates responses/ with the current rules and no
  API calls; --write stages recovered entries, --langs and --verbose
- tests: six cases covering the floor, replacing the old rejection test

Replaying all 38 saved responses took the reject rate from 20 entries to
zero. staging.db now holds 746 words / 774 senses / 3,436 translations
with no sense ranked above its easiest translation.

Docs also record the API quota ceiling found today: the free tier allows
about 20 requests/day, not the 1,000 previously assumed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 12:34:37 +02:00
.forgejo/workflows chore: add husky pre-commit and pre-push hooks 2026-04-30 01:15:14 +02:00
.husky chore: add husky pre-commit and pre-push hooks 2026-04-30 01:15:14 +02:00
apps updating documentation, prettier format 2026-08-02 01:01:33 +02:00
data-pipeline flooring sense difficulty instead of rejecting the entry 2026-08-20 12:34:37 +02:00
documentation flooring sense difficulty instead of rejecting the entry 2026-08-20 12:34:37 +02:00
packages Add words, senses, translations schema migration 2026-07-24 00:23:56 +02:00
.dockerignore infra: add Docker Compose setup for local development 2026-03-25 18:56:04 +01:00
.env.example adding pipeline db credentials and gemini api key 2026-07-24 13:26:20 +02:00
.gitignore implementing phase 3 pipeline: gemini structured output, validation, sqlite staging 2026-08-09 19:04:04 +02:00
.prettierignore chore: configure root eslint with react and tanstack router rules 2026-03-21 19:32:38 +01:00
.prettierrc chore: configure prettier with ignore rules and format scripts + running format 2026-03-20 18:37:38 +01:00
Caddyfile feat(caddy): add security headers for frontend 2026-04-23 21:45:35 +02:00
CLAUDE.md updating docs to match the implemented phase 3 pipeline 2026-08-20 12:10:48 +02:00
docker-compose.yml updating documentation, prettier format 2026-08-02 01:01:33 +02:00
eslint.config.mjs feat: add db schema, init, and vitest config 2026-05-03 17:56:29 +02:00
mise.toml setting up python env, download word data 2026-03-26 11:41:46 +01:00
package.json feat: add db schema, init, and vitest config 2026-05-03 17:56:29 +02:00
pnpm-lock.yaml feat: add db schema, init, and vitest config 2026-05-03 17:56:29 +02:00
pnpm-workspace.yaml adding the data-pipeline to ts and pnpm workspaces 2026-04-20 09:05:27 +02:00
README.md updating documentation, prettier format 2026-08-02 01:01:33 +02:00
tsconfig.base.json formatting 2026-03-21 19:33:07 +01:00
tsconfig.json formatting 2026-04-28 13:18:18 +02:00
vitest.config.ts chore: configure vitest with project-based setup and coverage 2026-03-20 19:25:00 +01:00

Lila

Learn words. Beat friends.

Lila is a vocabulary trainer that turns the media you love into language practice. Learn vocabulary from a Shakira song, the first chapter of Harry Potter, or an episode of Breaking Bad — then challenge your friends in real-time multiplayer quizzes.

Live at lilastudy.com.


Quickstart

# 1. Clone and install
git clone git@git.lilastudy.com:forgejo-lila/lila.git
cd lila
pnpm install

# 2. Environment
cp .env.example .env

# 3. Start local services (PostgreSQL, Valkey)
docker compose up -d

# 4. Build shared packages
pnpm --filter @lila/shared build
pnpm --filter @lila/db build

# 5. Run migrations
pnpm --filter @lila/db migrate

# 6. Start dev servers
pnpm dev

API: http://localhost:3000 · Web: http://localhost:5173

See DEPLOYMENT.md for production infrastructure details.


Documentation Index

Document What you'll find there
STATUS.md Current state — what's working, what's blocked, what we're building now
BACKLOG.md Prioritized task list: now / next / later / changelog
ARCHITECTURE.md Monorepo structure, layered architecture, data flow
DECISIONS.md Why we chose X over Y — tool choices, schema design, trade-offs
DATA_PIPELINE.md Gemini → SQLite staging → PostgreSQL: flow, current state, phase status
pipeline/design-doc.md Schema design, difficulty model, query patterns, Gemini JSON contract
pipeline/roadmap.md Phase plan for the pipeline and schema migration
DEPLOYMENT.md Hetzner VPS, Caddy, Docker Compose, CI/CD, backups
design/GAME_MODES.md Planned multiplayer and singleplayer game modes
archive/ Superseded docs — the removed local-LLM pipeline, CEFR voter strategy

Stack

Layer Technology
Monorepo pnpm workspaces
Frontend React 19, Vite, TanStack Router, Tailwind CSS
Backend Node.js, Express, TypeScript, WebSockets (ws)
Database PostgreSQL + Drizzle ORM
Auth Better Auth (Google + GitHub)
Validation Zod (shared between frontend and backend)
Testing Vitest, supertest
Deployment Docker Compose, Caddy, Hetzner VPS
CI/CD Forgejo Actions

Current Status

  • ✅ Singleplayer quiz (5 language pairs: en↔it/de/es/fr)
  • ✅ Multiplayer lobby + real-time game (2–4 players, simultaneous answers, 15s timer)
  • ✅ Auth (Google + GitHub)
  • ✅ Live deployment with CI/CD
  • 🔄 Rewriting the vocabulary data pipeline around Gemini + a sense-based schema
  • 🔄 Phase 7 hardening (rate limiting, error boundaries, monitoring)

See STATUS.md for the full picture.


Repository Structure

lila/
├── apps/
│   ├── api/           — Express backend
│   └── web/           — React frontend
├── packages/
│   ├── shared/        — Zod schemas + constants (API/web contract)
│   └── db/            — Drizzle schema, migrations, models, seeding
├── data-pipeline/     — Gemini generation → SQLite staging → PostgreSQL
├── documentation/   — Project docs (this directory)
└── Caddyfile, docker-compose.yml, etc.