7.4 KiB
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 and 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
- Create
src/lib/question-sets/<name>.tsexporting aQuestionSet. - Register it in
src/lib/question-sets/index.ts(import + add to thequestionSetsarray). - Run
npm run checkto confirm types compile. - (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_VALUESinsrc/lib/types.ts. Never invent other numbers (no 400, no 750).
Exact data shape
Mirror of Question / Category / QuestionSet in src/lib/types.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 inlocalStorage, so never rename it after release.category.id— unique within the set. Stable. Used in the played-question keycategoryId:questionId.question.id— unique within the category (typicallyq1..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
creativequestions, 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:
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/<name>.ts; its export is aQuestionSet. set.idis unique across all sets and kebab-case.- Exactly 5 categories; each
category.idunique within the set. - Exactly 5 questions per category; each
question.idunique within its category. - Each category's points are exactly
100, 200, 300, 500, 1000in order. - Every question has
typeofstrictorcreative. 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
questionSetsinindex.ts. npm run checkpasses (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 theGameStateshape. - 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.tsbeyond what content needs (usually nothing). - Commit, push, deploy, or edit
AGENTS.mdand other files underdevelopment/_reference/ai/.
If a needed change falls outside these boundaries, stop and report it; do not expand scope on your own.