# Question Authoring Guide (for AI agents) How to create or extend a question set for the calm family quiz **without touching code, state, or UI**. Question sets are pure data files. > You are a bounded worker. Read [AGENTS.md](../../../AGENTS.md) and > [autonomous-agent-harness.md](autonomous-agent-harness.md) first. This guide > covers **content data only**. Do not change UI components, the game store, the > types (beyond what content needs — usually nothing), or add backend / auth / > editor / multiplayer unless your task explicitly asks. ## TL;DR workflow 1. Create `src/lib/question-sets/.ts` exporting a `QuestionSet`. 2. Register it in `src/lib/question-sets/index.ts` (import + add to the `questionSets` array). 3. Run `npm run check` to confirm types compile. 4. (Only if your task asks) smoke-test in the browser with `npm run dev`. The selector screen lists sets from `questionSets` automatically — no UI edit needed. ## Hard structure rules (non-negotiable) Every set must match this shape **exactly**: - **Exactly 5 categories** per set (`set.categories.length === 5`). - **Exactly 5 questions** per category. - **Fixed point values per category, in order:** `100, 200, 300, 500, 1000`. - These values come from `POINT_VALUES` in `src/lib/types.ts`. Never invent other numbers (no 400, no 750). ## Exact data shape Mirror of `Question` / `Category` / `QuestionSet` in `src/lib/types.ts`: ```ts import type { QuestionSet } from '$lib/types'; export const mySet: QuestionSet = { id: 'my-set', // globally unique, kebab-case, stable forever title: 'Моя тема', description: 'Короткое тёплое описание.', ageRange: '6+ лет', categories: [ { id: 'cat-1', // unique WITHIN this set, stable title: 'Категория', questions: [ { id: 'q1', points: 100, question: '…', answer: '…', type: 'strict' }, { id: 'q2', points: 200, question: '…', answer: '…', optionalHint: '…', type: 'strict' }, { id: 'q3', points: 300, question: '…', answer: '…', type: 'strict' }, { id: 'q4', points: 500, question: '…', answer: '…', type: 'creative' }, { id: 'q5', points: 1000, question: '…', answer: '…', type: 'strict' } ] } // …4 more categories (5 total) ] }; ``` ## Unique ids (stability matters) - `set.id` — unique across **all** sets (e.g. `animals`, `cozy`, `space`). Lowercase kebab-case. It is persisted in `localStorage`, so never rename it after release. - `category.id` — unique **within the set**. Stable. Used in the played-question key `categoryId:questionId`. - `question.id` — unique **within the category** (typically `q1..q5`). Stable. Changing any id after release breaks saved progress for players mid-game. Treat ids as immutable once shipped. ## Difficulty progression (100 → 1000) Within each category, questions run simple → hard. The number only labels it; the **wording** carries the difficulty: - **100** — obvious warm-up; most answer instantly. - **200** — easy; may need a second's thought. - **300** — solid mid-level. - **500** — needs real knowledge or reasoning. - **1000** — the hard capstone; satisfying to land. ## Question type: `strict` vs `creative` From `QuestionType` in `src/lib/types.ts`: - `strict` — there is one correct answer. Host button reads «Засчитать». Use for facts: «Какое животное…?», «Где живут белые медведи?». - `creative` — open-ended, many acceptable answers. Host button reads «Засчитать творческий ответ» (softer framing, no "wrong" feeling). Use for imagination prompts: «Придумай…», «Опиши…». A category of facts is mostly/entirely `strict`; a category of imagination is mostly/entirely `creative`. A set can mix freely. The example sets (`animals.ts`, `cozy.ts`) keep roughly one `creative` category per set for balance. ## `optionalHint` — scaffold, don't reveal `optionalHint?: string` is an optional nudge the host can show on demand. - **Why it costs points:** showing a hint means the answer can then only be awarded at **half** value (see Boundaries). So it's a fair, pressure-free trade — omit it whenever no scaffold genuinely helps. - **Do** point at a category, sense, rhyme, or well-known association: - «Его часто называют царём зверей.» (for «Лев») - «Мама у него — кобыла, а папа — жеребец.» (for «Жеребёнок») - **Don't** restate or obviously give away the answer: - ❌ «Это лев.» - ❌ «Ответ начинается на букву „Л“.» - **For `creative` questions**, the hint can loosen imagination instead of narrowing it («Чем нелепее и добрее — тем лучше.»). - Keep it to **one short sentence**. Omit the field entirely when no scaffold helps — it is genuinely optional. ## Tone: calm, warm, Russian, family-friendly All user-facing text (`title`, `description`, `question`, `answer`, `optionalHint`) is in **Russian** and must stay calm and family-safe: - Soft, friendly phrasing; no words implying timers, pressure, or rush. - No scary, crude, political, or adult content. - Friendly to kids and grandparents together; avoid slang that ages badly. - Match the cozy register of the existing sets (`animals.ts`, `cozy.ts`). When unsure, read the existing sets and mirror their voice. Aim for a warm bedtime-evening mood. ## Register the set In `src/lib/question-sets/index.ts`: ```ts import { mySet } from './my-set'; export const questionSets = [animalsSet, cozySet, mySet]; ``` Order in the array is the order on the selector screen — new sets usually go last. ## Validation checklist (run before reporting done) - [ ] File is `src/lib/question-sets/.ts`; its export is a `QuestionSet`. - [ ] `set.id` is unique across all sets and kebab-case. - [ ] Exactly 5 categories; each `category.id` unique within the set. - [ ] Exactly 5 questions per category; each `question.id` unique within its category. - [ ] Each category's points are exactly `100, 200, 300, 500, 1000` in order. - [ ] Every question has `type` of `strict` or `creative`. - [ ] `optionalHint` (if present) scaffolds without revealing the answer; ≤ 1 sentence. - [ ] All copy is Russian, calm, family-friendly; matches the existing sets' tone. - [ ] Set is imported and added to `questionSets` in `index.ts`. - [ ] `npm run check` passes (types + svelte-check). ## Boundaries — do NOT (unless your task explicitly says so) - Add backend, database, auth, accounts, or multiplayer. - Add a question editor UI or any new component / route. - Edit the game store (`src/lib/stores/game.ts`) or the `GameState` shape. - Change scoring, hint, or partial-credit mechanics — they already exist and are fixed by the UI/state contract: - Full points: host «Засчитать +N». - Half points: host «Засчитать частично +N/2» (shown only when the hint was **not** revealed; `halfPoints = Math.round(points / 2)`). - Hint revealed → the answer can only be awarded at half value, and the partial-credit button is hidden. - Refactor `src/lib/types.ts` beyond what content needs (usually nothing). - Commit, push, deploy, or edit `AGENTS.md` and other files under `development/_reference/ai/`. If a needed change falls outside these boundaries, stop and report it; do not expand scope on your own.