QTI 3 ASI as the canonical assessment model
Status: accepted
We adopt QTI 3.0.1 ASI (the normalized JavaScript form from @conform-ed/contracts)
as the canonical internal representation for assessment items and tests — a
superset: QTI core plus namespaced Native Extensions. Anything expressible in QTI
round-trips losslessly to/from XML; extensions (e.g. pronunciation scoring, spaced
repetition) are emergent-only and explicitly outside the interop guarantee.
This reverses the earlier native-first direction (packages/domain/native-assessment.ts
and the qti.ts/qti-adapter.ts envelope), which a future reader would otherwise
assume is current. The assessment_definition.authoring_standard enum (native | qti3)
lets legacy rows coexist; no big-bang migration.
- Interop and standards-alignment are core goals (offline/in-person teaching support and a research programme), not afterthoughts. A superset model gives lossless QTI interchange by construction, deleting the native↔QTI mapping layer where lossiness and drift would otherwise live.
- We already own the model: conform-ed’s v3_0_1 contracts are MIT and deliberately a normalized JS representation, so the GPLv3 web-component libraries (e.g. Citolab) are irrelevant — we build a closed renderer on our own MIT contracts.
- The research stack (Results Reporting, Usage Data / Item Statistics, CAT) is already contracted in conform-ed and keys off QTI identities.
Considered and rejected
Section titled “Considered and rejected”- Native model + thin QTI export adapter. Smaller now, but two models plus a bidirectional map to keep correct forever; defers, not avoids, the work.
- Full-spec rendering as a launch gate. Conflates “QTI as the model” (a clean commitment) with “render the entire spec first” (a scope trap with no forcing function). We take the model commitment; rendering accrues incrementally per interaction, driven by language-learning need.
Consequences
Section titled “Consequences”- Embedded HTML in item bodies is currently modeled as a generic node, so schema
validation does not sanitize. The renderer must apply an allowlist tree-walk
(never
dangerouslySetInnerHTML); contracts are tightened later to subsume it. - Superset discipline requires a CI round-trip gate: every core-only item must survive
import→export with no loss, tested against the
conform-ed/tmp/qti-examplescorpora.