From 866c0a9f2d41b436ddbc283d5031f50a6c8c3d63 Mon Sep 17 00:00:00 2001 From: Falk Graepel Date: Sat, 16 May 2026 18:59:34 +0200 Subject: [PATCH] add agents.md --- AGENTS.md | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..556ac1c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,118 @@ +# AGENTS.md + +Guidance for AI agents working in this repo. Read this before making changes. + +## Project at a Glance + +- **What it is:** An offline-first PWA helper for the German tabletop RPG _Das Schwarze Auge 4.1_ (DSA 4.1). Covers character sheet, melee/ranged combat, spells, and import/export. +- **Stack:** SvelteKit 2 (SPA via `adapter-static`) + Svelte 5 + TypeScript (strict) + Vite 6. +- **Persistence:** IndexedDB via Dexie (`src/lib/storage/db.ts`); meta key/value table tracks the active character. +- **Validation:** Zod schemas in `src/lib/schema/`. +- **PWA:** `@vite-pwa/sveltekit` with autoUpdate; manifest in `vite.config.ts`. +- **Language:** UI, copy, identifiers, and most code comments are **German**. Preserve German wording (`Eigenschaften`, `Talente`, `Sonderfertigkeiten`, `Vorteile`, `Nachteile`, attribute keys like `MU/KL/IN/CH/FF/GE/KO/KK`, …) – don't translate domain terms. + +## Commands + +| Task | Command | +| ----------------- | ---------------- | +| Install deps | `npm install` | +| Dev server | `npm run dev` | +| Production build | `npm run build` | +| Preview build | `npm run preview`| +| Type / svelte check | `npm run check` | +| Lint | `npm run lint` | +| Format | `npm run format` | +| Run tests (CI) | `npm test` | +| Watch tests | `npm run test:watch` | +| Regenerate icons | `npm run icons` | + +After substantive edits, run `npm run check` and `npm test` before declaring done. + +## Repository Layout + +``` +src/ + app.css, app.html, app.d.ts + lib/ + characters/ # Character defaults / factories (newCharacter) + components/ # Shared Svelte components (e.g. DiceRoller) + engine/ # Pure derivation: AT/PA/FK basis, LeP, melee, ranged, probe, talent-check, spell + import/ # Helden-Software importer (placeholder) + rules/ # DSA 4.1 rule tables: attributes, races, talents, weapons, SFs, Vor-/Nachteile + schema/ # Zod schemas + schema version / migration + storage/ # Dexie DB, repo (CRUD), io (JSON/YAML export/import) + routes/ + +layout.{svelte,ts}, +page.svelte + characters/[id]/{sheet,combat/melee,combat/ranged,spells}/+page.svelte + settings/+page.svelte +tests/ + setup.ts # vitest setup (uses fake-indexeddb) + engine/ # Unit tests for derivation, ranged, io +scripts/ + write-placeholder-icons.mjs # runs on postinstall + `npm run icons` +static/ + favicon.svg, icons/ +``` + +Use SvelteKit aliases: `$lib/...` (resolves to `src/lib`) and `$app/...` for kit internals. Don't introduce relative `../../lib` imports. + +## Conventions + +### Formatting & Linting + +- Prettier: **tabs**, single quotes, no trailing commas, `printWidth: 100`. `*.svelte` uses the Svelte parser via `prettier-plugin-svelte`. +- ESLint flat config (`eslint.config.js`) extends `@eslint/js`, `typescript-eslint`, and `eslint-plugin-svelte`. `build/`, `.svelte-kit/`, and `node_modules/` are ignored. +- Run `npm run format` and `npm run lint` before finishing a change. + +### TypeScript + +- `strict: true` in `tsconfig.json` (extends `.svelte-kit/tsconfig.json`). `allowJs` and `checkJs` are on – stray `.js` files are type-checked too. +- Prefer `import type { ... }` for type-only imports. +- No `any`. Use Zod inference (`z.infer`) for domain types; the canonical `Character` type lives in `src/lib/schema/character.ts`. + +### Svelte 5 + +- Components are Svelte 5. Use the new runes where appropriate (`$state`, `$derived`, `$effect`, `$props`); don't reintroduce legacy `export let` style for new code. +- `svelte.config.js` filters the `a11y_label_has_associated_control` warning and the ESLint config relaxes it because fields use visual labels. Keep that pattern – don't add `for`/`id` plumbing just to silence warnings. + +### Domain Rules (read carefully before touching `engine/` or `rules/`) + +- Derived values follow DSA 4.1 formulas in `src/lib/engine/derived.ts`. They are pure functions of `Character`; don't mutate the input. +- Attribute access goes through `effectiveAttr(char, key)` (= `startwert + mod`). Don't read raw values directly when computing derived stats. +- Race modifiers come from `getRaceDef(char.meta.rasse)` (`src/lib/rules/races.ts`). New races must provide `lep_mod`, `asp_mod`, `aup_mod`, `mr_mod` so the engine keeps working. +- Sonderfertigkeiten / Vor- / Nachteile each have a typed table in `src/lib/rules/*.ts` and a getter (`getSonderfertigkeit`, …). Add new entries to the table; don't hard-code IDs in engine code. + +### Schema & Migrations + +- `CURRENT_SCHEMA_VERSION` lives in `src/lib/schema/version.ts`. Every persisted `Character` carries `schemaVersion` (a `z.literal`). +- When you change the character schema in a breaking way: + 1. Bump `CURRENT_SCHEMA_VERSION`. + 2. Update `migrateCharacter` in `src/lib/schema/version.ts` to migrate old payloads forward. + 3. Update / add tests in `tests/engine/io.test.ts` (or a new test) covering the migration path. +- Importers (`src/lib/storage/io.ts`, `src/lib/import/helden.ts`) must run input through `migrateCharacter` before `parseCharacter`. + +### Storage + +- All DB access goes through `src/lib/storage/repo.ts`. Don't `import { db }` from components – use `listCharacters`, `getCharacter`, `saveCharacter`, `deleteCharacter`, and the active-character helpers. +- The Dexie schema is in `src/lib/storage/db.ts`. Adding a new store or index requires bumping the Dexie `version(N)` and providing an upgrade function. + +## Testing + +- Test runner: Vitest (`npm test` / `npm run test:watch`). Config lives in `vite.config.ts` (`test.include` + `tests/setup.ts`). +- `tests/setup.ts` wires up `fake-indexeddb` so Dexie works in Node. Don't import real browser globals in tests. +- Add tests next to existing ones under `tests/engine/` for any new derivation, rules logic, or schema migration. Keep them deterministic (no real time/random unless seeded). +- When changing `engine/derived.ts`, re-check `tests/engine/derived.test.ts` because it pins the exact DSA 4.1 rounding (`Math.round` for AT/PA/FK/INI/MR, `Math.floor` for LeP base). + +## Build & PWA Notes + +- SPA mode: `adapter-static` with `fallback: 'index.html'` and `strict: false`. Don't introduce server-only endpoints (`+server.ts`, `+page.server.ts`) – the app must build as a static bundle. +- Workbox precaches `client/**/*.{js,css,ico,png,svg,webp,woff,woff2}`. If you add new asset types that should be cached offline, extend `workbox.globPatterns` in `vite.config.ts`. +- `postinstall` runs `scripts/write-placeholder-icons.mjs` to generate placeholder PNGs. Real production icons should replace `static/icons/icon-192.png`, `icon-512.png`, and `maskable-512.png`. + +## Things to Avoid + +- Don't add server-rendered routes, server hooks, or anything that breaks `adapter-static`. +- Don't bypass Zod – every external payload (import, future API) must go through `parseCharacter` (after migration). +- Don't hardcode rule data inside components; put it in `src/lib/rules/` so it can be reused and tested. +- Don't switch indentation, quote style, or trailing-comma policy – Prettier owns formatting. +- Don't translate German domain vocabulary or rename attribute keys; existing data and tests depend on them.