Methodology: mapping the bio_oge bank to official OGE exam task numbers
Question this answers: the open FIPI task bank tags every biology question with a КЭС (content codifier, e.g. 7.9 Обмен веществ...) and an answer_type_code (see scraper/answer_types.py) — but not the official exam task number (№1 through №26). This document derives that mapping from FIPI's own official documents, sourced and read directly (not guessed), and is honest about where the derivation is exact vs. a best-effort group. It mirrors METHODOLOGY.md's approach for math (math_ege_profil) — same philosophy, separate document because OGE biology's numbering, structure, and answer-type taxonomy are entirely different from EGE math's.
Primary sources (official, read directly — not summaries of summaries)
All fetched from FIPI's own document server (doc.fipi.ru), the authoritative source — not a third-party test-prep site. PDFs are re-hosted here so you can open them directly: Методология on the dashboard links every one of these inline.
| Document | 2026 (current, ratified) | 2027 (draft) |
|---|---|---|
| Спецификация (specification — exam structure, part/type/scoring tables) | ||
| Кодификатор (codifier — full content-element list) | ||
| Демонстрационный вариант (demo — a full real example exam with answer key) |
This document uses the 2026 spec as primary (it's the current, ratified — not draft — version), unlike math's METHODOLOGY.md which deliberately targets 2027 because math's profile-level exam is being restructured (19→20 tasks) next year. Biology has no such restructuring: the 2026 spec's own §12 states "Изменения структуры и содержания КИМ отсутствуют" (no structural changes vs. 2025), and a first-page skim of the 2027 kodifikator draft shows the same content-section numbering (1–7) already present in 2026's codifier and in our own scraped codifiers column — so there's no forward-looking reason to prefer the draft here. The 2027 documents are still hosted above for reference/comparison.
Exam structure (from the 2026 specification, §6–7)
26 tasks, two parts, 47 max points, 150 minutes:
- Part 1 (tasks 1–21): short answer (21 tasks, 34 points, 72% of the total).
- Part 2 (tasks 22–26): extended answer (5 tasks, 13 points, 28% of the total) — this is answer_type_code = 'extended_answer' in our schema, and, exactly like math's Развёрнутый ответ, has no FIPI answer-checker at all. It is deliberately untouched by this project, same reasoning as math's open-answer part (see OPEN_ANSWER_METHODOLOGY.md).
Task-by-task answer type — verified against the real demo variant, not the abstract spec table alone
The specification's own appendix ("Обобщённый план") states the counts and content-codes per task, but its two-column PDF layout doesn't extract cleanly enough to trust as an exact table (see "What's exact vs. best-effort" below). Instead, every one of the 26 tasks below was read directly off the actual 2026 demo variant — a real example question, in the real format, for every task number — which is unambiguous: you can see exactly what shape of question and answer each number is.
| Task № | Our answer_type_code |
What the demo example actually is |
|---|---|---|
| 1 | short_answer |
"Какое ОБЩЕЕ свойство живых систем иллюстрирует..." — word/phrase answer |
| 2 | matching |
Organisms → kingdoms (А,Б,В,Г → 1,2,3,4) |
| 3 | sequence |
Systematic taxa, smallest→largest (5 items → 5-digit sequence) |
| 4 | multi_choice |
Reading a growth-curve graph, pick 2 of 5 correct descriptions |
| 5 | sequence |
Ordering instructions/process steps (6 or 5 items) |
| 6 | single_choice |
"Как называется прибор, изображённый на рисунке?" |
| 7 | multi_choice |
Pick 3 of 6 statements matching a given organism's traits |
| 8 | single_choice |
Fill a missing concept in a 2-row object/function table |
| 9 | multi_choice |
Pick 3 of 6 organisms matching a criterion |
| 10 | term_placement |
Cloze text, 4 blanks (А,Б,В,Г), numbered term list |
| 11 | matching |
Traits → processes (up to 6 pairs, А–Е) |
| 12 | single_choice |
"Верны ли следующие суждения..." — a fixed template, any topic |
| 13 | matching |
Compare a photographed organism's traits to reference models (rare, multi-part; not reliably separable from bank metadata — see below) |
| 14 | single_choice |
Identify a labeled organ/structure in an image |
| 15 | single_choice |
Name a described life-process/phenomenon |
| 16 | multi_choice |
Pick 3 correct labels on a diagram |
| 17 | multi_choice |
Pick 3 of 6 structures matching a physiological function |
| 18 | matching |
Bones → skeletal regions (up to 6 pairs) |
| 19 | multi_choice |
Pick 3 ecological-role characteristics for an organism in a food web |
| 20 | sequence |
Food chain from a food-web diagram — answer is LETTERS (diagram nodes labeled А, Б, В...), not digits — the one sequence task with a different answer alphabet |
| 21 | matching |
Predict how one variable changes given another, per row of a small table (values can repeat) |
| 22–26 | extended_answer |
Free-form written answers, human-graded — not attempted |
Counts match the specification's declared totals exactly: 5×single_choice (6,8,12,14,15), 6×multi_choice (4,7,9,16,17,19), 5×matching (2,11,13,18,21), 3×sequence (3,5,20), 1×term_placement (10), 1×short_answer (1), 5×extended_answer (22–26) = 26.
Answer-submission format per type (separately reverse-engineered, see BIO_OGE_ANALYSIS.md and WORKLOG.md 2026-09-15)
Not part of the task-numbering question above, but the other half of "understanding this exam": single_choice = bare digit; multi_choice = positional binary string over every checkbox in order (not the selected numbers concatenated — that was tried first and FIPI's checker rejected it); sequence/matching/term_placement = concatenated digits in position order; short_answer = plain text. All confirmed empirically against the real FIPI checker, not assumed.
What's exact vs. best-effort — read this before trusting a number
Same principle as math's METHODOLOGY.md: where the bank's own metadata (codifier + answer type) uniquely determines a task number, it's exact; where several task numbers share the same signature and can't be told apart, they're grouped honestly rather than guessed.
scraper/assign_oge_task_numbers.py encodes these rules:
- Unique by answer type alone (exact, no further work needed):
short_answer→1,term_placement→10 — each is the only task using that answer type, so every row of that type gets that number with full confidence. sequence(3 task numbers, split by content): task 20 detected by codifier section 2 (ecosystems) or food-chain keywords, OR (as a confirming signal on already-solved rows) a letter-containingcorrect_answer; task 3 by codifier sections 5/6 (plant/animal systematics) or taxonomy keywords; task 5 by elimination (whatever's left). All three came out exact — 149/149 sequence questions classified, no group needed.single_choice(5 task numbers): task 12 detected via FIPI's own fixed phrase "Верны ли следующие суждения" in the question text (a format signal, not content — codifier keywords can't find this one, since task 12 can be about any topic); task 6 by scientific-method/instrument keywords; tasks 14 and 15 are grouped — both draw on the same broad "human body" codifier section (7.x) with nothing in our scraped metadata to tell "identify this organ in a picture" (14) apart from "name this life process" (15); task 8 is the residual.multi_choice(6 task numbers): tasks 4 (codifier section 1) and 19 (section 2) came out exact; tasks 7 and 9 are grouped (both organism-classification content, section 4/5/6) and tasks 16 and 17 are grouped (both human-body content, section 7) — same fundamental limitation as math's grouped buckets: the bank simply doesn't record which specific task template a question was drawn from, only its topic and answer shape.matching(5 task numbers): tasks 2 (kingdoms/systematics), 18 (skeleton, "скелет"/"кост" keywords), and 21 (ecosystem section) came out exact; task 11 (general human-process matching) is the residual for section-7 matching questions; task 13 (the rare photo-comparison-to-models format) is left unclassified — nothing in our scraped codifier/text distinguishes it from task 11's ordinary matching, and it's genuinely rare in the source exam (one distinct sub-format among five matching tasks), so grouping it in with 11 would silently misrepresent items that may not actually be task 13 at all. Better to leave itNULLthan assign a number with no real signal behind it.extended_answer: not classified at all (matches math's precedent) — no verification methodology exists for this type yet regardless of task number, so a task-number label would be pure decoration with no functional use.
Result on the real 1979-question bank (2026-09-15 run): 978 exact, 510 grouped, 491 unclassified (355 of those are extended_answer, the deliberately-untouched part — only 136 rows out of 1979 have genuinely no task-number signal).
Implementation
scraper/assign_oge_task_numbers.py applies the rules above over codifiers + answer_type_code + question_text (+ correct_answer as a secondary signal for task 20), writing:
- questions.oge_task_number — a single int when exact, NULL when grouped or unclassified
- questions.oge_task_group — e.g. '14,15' when grouped, NULL otherwise
- questions.oge_task_confidence — 'exact' | 'grouped' | NULL
These are separate columns from ege_task_number/ege_task_group/ege_task_confidence (math's columns) — not reused, since OGE's numbering is an entirely independent scheme from EGE's (see schema.sql's comment on why). Re-run assign_oge_task_numbers.py any time this rule table is revised or the bank is re-scraped — it's idempotent, just re-derives and overwrites these three columns for every bio_oge row.
The dashboard's "Номер задания ОГЭ" filter (fipi.lungu.ru) and the tutor's task-selection (fipi_bank.js problem --oge-task N) both read these columns directly — see TUTOR_INTEGRATION.md and AGENTS.md in the ioiva/tutor repo for how Varya can ask for a specific exam task number and have it threaded through.