diff --git a/README.md b/README.md index f569b0a..1274e9c 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,17 @@ npm run check # проверка типов (svelte-check) Чем дороже карточка, тем сложнее вопрос. 3. Ведущий открывает вопрос, затем «Показать ответ», и решает: - **Засчитать +N** — команде идут очки; + - **Засчитать частично +N/2** — для «почти правильного» ответа ведущий может + дать половину стоимости вопроса; - **Не засчитывать** — без очков, но вопрос закрыт. - Штрафов и минусов нет. -4. Для творческих вопросов (type `creative`) кнопка мягче: +4. У некоторых вопросов есть необязательная **подсказка** 💡. Ведущий может + показать её по желанию. Если подсказка показана — ответ засчитывается только + за половину стоимости: мягкая помощь без давления. +5. Для творческих вопросов (type `creative`) кнопка мягче: «Засчитать творческий ответ +N». -5. Сыгранный вопрос затемняется и больше не выбирается. -6. Когда сыграны все вопросы — экран результата с мягкой финальной фразой. +6. Сыгранный вопрос затемняется и больше не выбирается. +7. Когда сыграны все вопросы — экран результата с мягкой финальной фразой. Прогресс сохраняется автоматически — после перезагрузки игра продолжится с того же места. @@ -41,6 +46,11 @@ npm run check # проверка типов (svelte-check) Архитектура задумана так, чтобы наборы добавлялись без правок UI. +**Структура набора:** ровно **5 категорий**, в каждой ровно **5 вопросов** с +номиналами **100 / 200 / 300 / 500 / 1000** (от простого к сложному). Вопросы +бывают `strict` (однозначный ответ) и `creative` (творческий). У вопроса может +быть необязательное поле `optionalHint` — подсказка для ведущего. + 1. Создайте файл `src/lib/question-sets/.ts`: ```ts @@ -57,14 +67,14 @@ npm run check # проверка типов (svelte-check) title: 'Категория', questions: [ { id: 'q1', points: 100, question: '...', answer: '...', type: 'strict' }, - { id: 'q2', points: 200, 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' } // ровно 5 вопросов с очками 100/200/300/500/1000 ] } - // …остальные категории + // …ещё 4 категории (всего 5) ] }; ``` diff --git a/development/_reference/ai/README.md b/development/_reference/ai/README.md index 0454cd2..ae79390 100644 --- a/development/_reference/ai/README.md +++ b/development/_reference/ai/README.md @@ -10,6 +10,7 @@ Shared references for Codex and other AI coding agents in this project. | Autonomous agent harness | [autonomous-agent-harness.md](autonomous-agent-harness.md) | | Worker loop command | [scripts/run-agent-loop.mjs](scripts/run-agent-loop.mjs) | | Pi worker wrapper | [scripts/run-pi-worker.mjs](scripts/run-pi-worker.mjs) | +| Question authoring | [question-authoring.md](question-authoring.md) | Use `npm run agent:loop -- --task ""` when Codex delegates implementation to Pi. Codex remains the orchestrator, verifier, reviewer, and diff --git a/development/_reference/ai/question-authoring.md b/development/_reference/ai/question-authoring.md new file mode 100644 index 0000000..a194079 --- /dev/null +++ b/development/_reference/ai/question-authoring.md @@ -0,0 +1,173 @@ +# 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.