You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add a QTI assessment-item type and renderable preset-bit ordering #224
File.included_presets (studio Separated constants #8, kolibri Trying init file #10) is a bitmask whose bit positions derive from a stable preset ordering — like Kolibri's metadata-label bitmasks, which take each label's bit from its index in the le-utils ordered list.
The Change
Add a QTI assessment-item type to constants.exercises.
Define the preset→bit ordering for the renderable bitmask as append-only: existing presets keep their bit; new presets get the next.
Acceptance Criteria
constants.exercises exposes a QTI assessment-item type
A stable, append-only preset→bit mapping backs the renderable bitmask
Studio and Kolibri can both import the type and the bit mapping
Architecture decided with the maintainer across an iterative session: blanket QTI type with the item XML in raw_data; XSD-authoritative validation across all sources; a legacy→QTI global migration with an API-layer dual-read; ricecooker upload delegating to the AssessmentItem serializer; and a Perseus custom-interaction contract confirmed against the QTI 3.0 specification. Claude mapped the existing publish/validation/ricecooker code, proposed the breakdown, and drafted each issue; the maintainer steered every decision and reviewed throughout.
Ran this through a spec pass since it touches two ambiguous-looking spots in the codebase. Posting the resolution here rather than asking, since the codebase itself settles both — flag if either read is wrong.
QTI assessment-item type — constants.exercises gets QTI = "QTI", appended to question_choices. Uppercase is deliberate (breaks the file's existing lowercase-snake convention) because Studio's AssessmentItem.type choices are built directly from question_choices (contentcuration/models.py), and studio#5999 already fixes the literal as type='QTI'.
Preset→bit ordering — format_presets.py currently has two orderings of the same preset set that have already drifted apart: the hand-written choices display tuple and PRESETLIST (sourced from resources/presetlookup.json, dict/JSON order). E.g. video_dependency/video_thumbnail/video_subtitle and audio_thumbnail/audio_dependency appear in different relative order between the two, and choices has a precedent for silently dropping an entry (VIDEO_VECTOR, commented out). tests/test_presets.py::test_format_presets_are_synced only checks the two share the same set of keys, never the same order — confirming choices' order was never meant to be significant.
So the bit order is taken from PRESETLIST's existing order (i.e. presetlookup.json's), exposed as a small dedicated append-only id list (name TBD at implementation, e.g. RENDERABLE_PRESETS_ORDER) rather than a hand-maintained third ordering. Consumers compute 2 ** index themselves — le-utils only owns the order, mirroring the existing LEARNINGACTIVITIESLIST / Kolibri metadata-label-bitmask pattern this issue already points at (le-utils exposes the ordered list; kolibri/core/content/utils/search.py does the 2**j arithmetic). Not placed under constants/labels/ since that package is explicitly metadata-only and generated from specs — this is a functional preset concern, so it lives in format_presets.py next to PRESETLIST.
Full writeup: .specs/2026-07-02-qti-preset-bitmask-design.md (local scratch, not committed).
Plan: Add a QTI assessment-item type to constants.exercises and a stable, append-only preset→bit ordering list to constants.format_presets, so Studio and Kolibri can both import them for issue #224 (studio #1, studio #8, kolibri #10).
Add QTI assessment-item type
Add RENDERABLE_PRESETS_ORDER preset→bit ordering list
@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly
How was this generated?
Implemented code following the pre-approved plan using test-driven development (red-green-refactor)
Ran the project's full test suite and linter before committing
For UI changes: captured live screenshots to verify rendering
For backend changes: verified with example API/CLI output
Activity
rtibblesbot commentedon Jul 3, 2026
Scoping notes before implementation
Ran this through a spec pass since it touches two ambiguous-looking spots in the codebase. Posting the resolution here rather than asking, since the codebase itself settles both — flag if either read is wrong.
QTI assessment-item type —
constants.exercisesgetsQTI = "QTI", appended toquestion_choices. Uppercase is deliberate (breaks the file's existing lowercase-snake convention) because Studio'sAssessmentItem.typechoices are built directly fromquestion_choices(contentcuration/models.py), and studio#5999 already fixes the literal astype='QTI'.Preset→bit ordering —
format_presets.pycurrently has two orderings of the same preset set that have already drifted apart: the hand-writtenchoicesdisplay tuple andPRESETLIST(sourced fromresources/presetlookup.json, dict/JSON order). E.g.video_dependency/video_thumbnail/video_subtitleandaudio_thumbnail/audio_dependencyappear in different relative order between the two, andchoiceshas a precedent for silently dropping an entry (VIDEO_VECTOR, commented out).tests/test_presets.py::test_format_presets_are_syncedonly checks the two share the same set of keys, never the same order — confirmingchoices' order was never meant to be significant.So the bit order is taken from
PRESETLIST's existing order (i.e.presetlookup.json's), exposed as a small dedicated append-only id list (name TBD at implementation, e.g.RENDERABLE_PRESETS_ORDER) rather than a hand-maintained third ordering. Consumers compute2 ** indexthemselves — le-utils only owns the order, mirroring the existingLEARNINGACTIVITIESLIST/ Kolibri metadata-label-bitmask pattern this issue already points at (le-utils exposes the ordered list;kolibri/core/content/utils/search.pydoes the2**jarithmetic). Not placed underconstants/labels/since that package is explicitly metadata-only and generated from specs — this is a functional preset concern, so it lives informat_presets.pynext toPRESETLIST.Full writeup:
.specs/2026-07-02-qti-preset-bitmask-design.md(local scratch, not committed).No open questions — ready for implementation.
rtibblesbot commentedon Jul 3, 2026
Plan: Add a
QTIassessment-item type toconstants.exercisesand a stable, append-only preset→bit ordering list toconstants.format_presets, so Studio and Kolibri can both import them for issue #224 (studio #1, studio #8, kolibri #10).QTIassessment-item typeRENDERABLE_PRESETS_ORDERpreset→bit ordering list@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly
How was this generated?
feat: add QTI assessment-item type and renderable preset-bit ordering