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
Land assessment items uploaded through the internal/ricecooker API uniformly as QTI: store editor-shaped and arbitrary QTI directly, convert uploaded legacy/structured items to QTI via the #6 machinery, validate against the schema, and map referenced media.
Complexity: High Target branch: unstable
Context
create_exercises (contentcuration/contentcuration/views/internal.py) builds items from structured fields and validates only assessment_id uniqueness; type and content go unchecked until publish.
The internal endpoint and utils/nodes.py duplicate logic that the AssessmentItemViewSet/serializer (Introducing Content Curation #1) already owns; delegating to it cleans up that tech debt.
QTI items carry content as raw_data XML and reference media mapped via map_files_to_assessment_item (utils/nodes.py).
Arbitrary QTI may use interactions Studio can't edit; these are non-editable passthrough, published verbatim.
The Perseus custom interaction (data-type='perseus') is a publish-time-only wrapper (Browserify #8); if our own published QTI is re-imported, it must be unwrapped back to a raw perseus_question.
The Change
Refactor create_exercises to delegate to the AssessmentItemViewSet/serializer machinery (Introducing Content Curation #1), removing duplicated logic in the internal endpoint and nodes utils.
Unwrap any Perseus custom interaction (data-type='perseus'): read its referenced data-perseus-path payload from the upload and restore it as a raw perseus_question, rather than storing the custom interaction.
Map media/file dependencies so they are present at publish.
Acceptance Criteria
create_exercises delegates to the AssessmentItem serializer/machinery; duplicated internal-endpoint and nodes logic is removed
The API accepts and persists QTI items (raw_data XML + media)
Uploaded legacy/structured items are converted to QTI on ingest; raw Perseus is preserved as-is
A Perseus custom interaction is unwrapped by reading its data-perseus-path payload and restoring the raw perseus_question
Referenced media is mapped and present at publish
Tests cover QTI upload (editor-shaped + arbitrary), legacy-converted-on-ingest, an invalid upload, and media mapping
References
contentcuration/contentcuration/views/internal.py
contentcuration/contentcuration/utils/nodes.py
AI usage
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.
Overview
Land assessment items uploaded through the internal/ricecooker API uniformly as QTI: store editor-shaped and arbitrary QTI directly, convert uploaded legacy/structured items to QTI via the #6 machinery, validate against the schema, and map referenced media.
Complexity: High
Target branch: unstable
Context
create_exercises(contentcuration/contentcuration/views/internal.py) builds items from structured fields and validates only assessment_id uniqueness; type and content go unchecked until publish.utils/nodes.pyduplicate logic that theAssessmentItemViewSet/serializer (Introducing Content Curation #1) already owns; delegating to it cleans up that tech debt.raw_dataXML and reference media mapped viamap_files_to_assessment_item(utils/nodes.py).data-type='perseus') is a publish-time-only wrapper (Browserify #8); if our own published QTI is re-imported, it must be unwrapped back to a rawperseus_question.The Change
create_exercisesto delegate to theAssessmentItemViewSet/serializer machinery (Introducing Content Curation #1), removing duplicated logic in the internal endpoint andnodesutils.QTIitems (raw_data XML + media) directly; validate each against the schema (Ant's backend plus setting up front end files #2), rejecting non-compliant items with actionable errors.data-type='perseus'): read its referenceddata-perseus-pathpayload from the upload and restore it as a rawperseus_question, rather than storing the custom interaction.Acceptance Criteria
create_exercisesdelegates to the AssessmentItem serializer/machinery; duplicated internal-endpoint andnodeslogic is removeddata-perseus-pathpayload and restoring the rawperseus_questionReferences
contentcuration/contentcuration/views/internal.pycontentcuration/contentcuration/utils/nodes.pyAI usage