ADR-084 — A text before an item: the intro of an evaluation item¶
Status¶
Accepted (2026-10-08, issue #455; the design in the issue was accepted by the
product owner, who asked for it to be built as written). Requirement
F-EVAL-34. Delivered in one pull request: migration 0085_item_intro, the
contracts, the builder's "+ Text" and the player's passage screen.
Scope: the column evaluation_items.intro, the item routes of an evaluation
and of a template (ItemPatch), the copies of an item list (duplicate,
Save as template, Instantiate, pull), the template's revision and pull
summary, AttemptItem (the attempt and the teacher's preview) and the zen
player.
Relations: extends ADR-031 (an intro is item content, like the milestone flag and the bonus flag of ADR-052); reads F-EVAL-07 and F-LIVE-08 as they stand, and changes neither.
Context¶
A teacher wants text that is not a question inside an evaluation: the
instructions at the start ("read chapters 8 and 9 of the handout, then
answer"), a transition mid-exam ("end of part 1; the next questions are
code"), a passage to memorise that disappears once the student moves on. A
reading task with a deadline is an exercise with such a text and two or
three comprehension questions (heig-classroom#52), which also tells the
teacher who actually read.
Decision¶
- An intro is a property of an item, not a question type. An item may
carry
intro, optional markdown of at most 10 000 characters, shown to the student as a passage screen before that item. A blank text is stored as none (null). It is the teacher's own content for this evaluation: never translated, never written into a pool. The item stays one question; an intro adds no item, no points, no answer. - Written through the item routes, under the item list's lock.
PATCH …/items/:itemIdwith{ intro }(a string, ornullto remove it), on an evaluation and on a template alike. It is part of what a student is shown, so it is frozen exactly like the points and the milestone flag (assertItemListEditable: no attempt,draftorscheduled). - Carried by every copy, and a change of it is a change of the item.
A duplicate, Save as template, Instantiate and a pull copy it with
the item. On a template, a write that changes an intro moves the
revision (it is part of
contentOf). A pull's summary lists an item whose intro differs aschanged("text before the question changed"), and the pull replaces it with the template's. - It reaches the student with the item, through the one builder of the
attempt.
AttemptItem.introis filled inattemptItems(live/attempt.ts), besidemilestoneandbonus: the attempt, its restore and the teacher's preview (ADR-018) all come through it. It is not question content and does not passtoStudent; it is an item property the teacher wrote for students to read, and nothing of a question's key, concepts (tags before ADR-081's cut-over) or explanation travels with it. - Not in grading, feedback, results nor the dashboard. None of those payloads carries it: they are about answers, and the intro asks none. The teacher reads it in the builder.
- The passage screen. In the zen player, arriving on an item that has an intro shows the text first, with one primary action, Continue, which shows the question. The question list (F-LIVE-09) still lists questions only: the intro has no segment, no mark, no number.
- When it shows. On arriving at the item, unless this player already passed it — or, on loading the attempt, unless the item is already started (an answer, "Leave unanswered", or validated). A student who reloads mid-question is not shown the text again.
freenavigation: it can be reopened at any time from the question it precedes ("Read the text again", beside the question's heading).forward_onlyandmilestones: Continue is one way: the text is not reopenable once passed, which is what makes "memorise this, then answer" work. The lock of a passed milestone is unchanged and generated by the platform (F-LIVE-08): "you won't be able to go back" is never the teacher's to write. A transition with a lock is amilestoneon the item before plus anintroon the item after.- Shuffled items carry their intro. Under
shuffleItemsan intro travels with its item, as the milestone flag already does: it is the item's, not a position's. The builder says nothing more; whether a shuffled paper should pin its intros was left open in 06 no. 55, settled 2026-10-08: it travels with its item.
Consequences¶
- One nullable column and one optional field; no special case in the total, the grading table, the summary, the statistics, the drill, the debrief, the "answered" counter, the flag or the validation — an intro is none of those things.
- The "passed" fact is held by the player, not stored: a student who reloads before starting a question sees its text again, even after a milestone. Acceptable for instructions and transitions; for "memorise", it is the limit recorded in 06 no. 55, accepted by the product owner on 2026-10-08.
- The builder reads as sections: a recessed band with the text's first lines above the item it precedes, and a "+ Text" control in each gap between items (and above the first).
Alternatives considered¶
- A "Description" question type worth 0 points (Moodle). Rejected: it would have to be excluded from the total, the grading table, the student's summary, the statistics, the discrimination, the drill, the debrief, the "answered" counter, the progress, the flag, "Leave unanswered" and "Validate and continue" — a dozen special cases — and evaluation-specific text would end up in pools.
- A separate list of sections on the evaluation. Rejected: an intro then needs an anchor that survives reorders, deletions, copies and pulls, which the item already is.
- Recording the passage on the server. Not done (06 no. 55, settled 2026-10-08 by the product owner): it needs a write per passage and a column on the answer, for a guarantee no teacher has asked for yet.