Skip to content

QTI 3.0 authoring breadth — §6 plan (PNP / feedback / adaptive / stimulus / rubric)

Companion to ADR-0021 §6. The interchange + conformance core (§1 conformance lane, §3 item export + Content-Package, §4 results emission) shipped 2026-06-16. This plan covers the remaining decision — §6: author the accessibility, feedback, adaptivity, shared-stimulus, and rubric constructs the engine already delivers and round-trips.

Framing (verified 2026-06-16). conform-ed’s engine already delivers, scores, serializes, and validates every construct below, and the :local corpus lane proves emergent’s pipeline round-trips the official examples that use them. The gap is purely emergent authoring UI — there is no round-trip/engine work here. This is therefore a teacher-portal authoring lane, the same character and scale as the §5 interaction-authoring build and ADR-0020 rich test authoring (each its own session). Execute it slice-by-slice; each slice is independently shippable + validated and extends test:qti:conformance with its emitted artifact.

Engine surface to wire (do not rebuild — ADR-0021 §2)

Section titled “Engine surface to wire (do not rebuild — ADR-0021 §2)”
construct conform-ed serializer / contract emergent authoring delta
AccessForAll PNP serializeQtiAccessForAllPnp (+…Records); QtiAccessForAllPnpDocument a PNP authoring surface (learner access profile) + per-item catalogInfo
item catalog (per-item AFA supports) QtiCatalogInfoSchema on every item raw schema item-draft catalogInfo (alternative text/spoken/braille support refs)
feedback item modalFeedbacks; feedbackBlock/feedbackInline in itemBody; QtiModalFeedbackSchema item-draft modal + inline feedback authoring (outcome-gated)
adaptive + templateProcessing item adaptive, templateDeclarations, templateProcessing; QtiTemplateProcessingSchema item-draft adaptive flag + template variables + template-processing builder
shared assessmentStimulus serializeQtiAssessmentStimulus; item assessmentStimulusRefs a stimulus authoring surface (bank) + item ref wiring
rubric blocks writeRubricBlocks at test/section/part; QtiTestRubricBlockSchema rubric authoring in the test-structure editor (ADR-0020 surface)

All authoring builders follow the proven pattern (§5, §4): construct conform-ed’s document model from emergent’s draft, guard with the contract schema’s .parse (loud drift), serialize through the engine. Mantine MCP first for every component (repo rule); i18n via typesafe-i18n (en + zh-Hans + bun run i18n:generate); no new deps.

Slices (each independently shippable + validated; feature branch per slice, rebased to land)

Section titled “Slices (each independently shippable + validated; feature branch per slice, rebased to land)”
  • Domain: extend the itemDraft union (qti-item-authoring.ts) with modalFeedbacks (identifier, outcomeIdentifier, showHide, title, content) and inline feedbackBlock nodes; map into the item document (buildAuthoredItemDocument), guard with QtiAssessmentItemDocumentSchema.
  • UI: a feedback editor in QtiItemAuthorPanel — per-outcome feedback blocks, show/hide on a declared outcome (reuse the outcome/condition vocabulary from ADR-0020’s ConditionBuilder).
  • Conformance: emitted item with feedback re-validates + re-ingests; add a feedback fixture.
  • Domain: adaptive flag, templateDeclarations, and a templateProcessing rule builder (a practical subset of setTemplateValue/templateConstraint, mirroring the RP expression authoring already in assessment-condition.ts). Guard via the contract.
  • UI: an “adaptive” toggle + template-variable + template-processing section in the item panel; render unsupported imported template rules read-only (the summarizeConditionExpression pattern).
  • Conformance: emitted adaptive item round-trips; corpus adaptive examples (e.g. Example05-feedbackBlock-adaptive) move from :local backlog into the deterministic set.
  • Domain: item-draft catalogInfo — alternative representations (spoken/braille/sign/text) keyed to body nodes; map to the item doc catalogInfo.
  • UI: an accessibility panel per item (add alternative content per support).
  • Conformance: emitted item with catalogInfo round-trips; add a catalog fixture (the corpus MultipleCatalogs / CatalogWithMultipleSupports examples are the reference).
  • Decision (O-1, Anton 2026-06-16): the learner PNP is learner-owned — a person-scoped accessibility profile (AccessForAll-correct + person-rooted identity ADR-0013); teacher/admin may author on a learner’s behalf (proxy) against the same per-person row; consumed at delivery + exportable.
  • Domain: a pnpDraftQtiAccessForAllPnpDocument builder + serializeQtiAccessForAllPnp wrapper (contract-guarded). Schema: a person-scoped accessibility-profile table + RLS (regenerate migrations — see “Migrations” below; the agent does this, the container gates apply it).
  • UI: a PNP authoring surface (access modes, hazards, text/visual/audio preferences).
  • Export + conformance: a …/pnp.xml export surface (mirrors results/qti.xml) + the AFA-PNP XSD joins the conformance fixtures; emitted PNP validates.
  • Decision (O-2, Anton 2026-06-16): a first-class stimulus bank (assessment_stimulus + assessment_stimulus_version, paralleling the item bank) so stimuli are reusable across items and packageable.
  • Domain: a stimulusDraftserializeQtiAssessmentStimulus builder (contract-guarded), plus item-draft assessmentStimulusRefs wiring. The stimulus then packages alongside items in the Content Package (extend buildQtiItemContentPackage).
  • Schema: the bank tables (regenerate migrations — see “Migrations”; container-gated, no dev-DB dependency).
  • UI: a stimulus authoring surface + an item-side “attach stimulus” picker.
  • Conformance: emitted stimulus validates; package round-trip includes a stimulus resource.
  • Domain: extend the ADR-0020 test-structure authoring (assessment-test.ts) with rubricBlocks at test/part/section level. NOTE: the conform-ed test view does not yet carry rubric blocks (assessmentTestViewFromNormalized drops them) — so this slice extends BOTH the conform-ed view (+ its assessmentTestDocumentFromView inverse) and emergent’s authoring. That conform-ed change ships in the same release cadence as any other engine gap.
  • UI: rubric editor nodes in the TestStructureEditor (view-restricted rich content).
  • Conformance: the emitted test carries rubric blocks and joins the conformance lane. Test export itself is already done (@conform-ed 0.0.23, branch qti-conformance-coverage; see “Test export” below); F only adds rubric blocks to the test view + inverse and to authoring.

A (feedback) → B (adaptive) → C (item catalog) → E (stimulus) → D (PNP) → F (rubric). A–C extend the existing item panel (cheapest, highest reuse); E + D add bank/profile schema (agent-regenerated, container-gated); F extends the test view + authoring. All buildable in one session — nothing is blocked on Anton (test export already shipped on @conform-ed 0.0.23; F’s rubric-on-the-test-view extension follows the normal conform-ed release cadence).

Migrations & DB (no dependency on Anton’s dev DB)

Section titled “Migrations & DB (no dependency on Anton’s dev DB)”

Slices D and E add schema. The agent regenerates the whole migration set itself per docs/runbooks/regenerate-migrations.md (§2–§6) and commits; new tables collapse into initial_baseline. The integration + conformance gates apply these migrations in ephemeral Podman containers, so a schema slice is fully built, validated, and landed by the agent — bun run test:integration green IS the bar. The dev-DB DROP/recreate + db:migrate:local (runbook §1/§7) is Anton’s non-blocking smoke-testing step, never a gate. (Anton, 2026-06-16: “You are free to delete/regenerate the migrations as needed. I will manage my own dev db.”) No structural DDL on Supabase-owned schemas; RLS via CREATE POLICY + a public SECURITY DEFINER helper (the qti_item_asset_storage_policies pattern).

Test export (the §3 remainder) — ✅ done (2026-06-16)

Section titled “Test export (the §3 remainder) — ✅ done (2026-06-16)”

@conform-ed/qti-react’s assessmentTestDocumentFromView (the inverse of assessmentTestViewFromNormalized, view→document→view idempotent across the full official tests/ corpus) shipped in @conform-ed 0.0.23 (now pinned). emergent wired test export with no further engine work: domain serializeAssessmentTest(structure) = serializeQtiAssessmentTest(assessmentTestDocumentFromView(assessmentTestViewFromTestStructure(structure))) (+ an itemHref resolver), GET /workflow/qti-tests/:assessmentDefinitionId/qti.xml, a self-contained test package in buildQtiItemContentPackage (.../package.zip), and emitted-test + emitted-test-package conformance gates — all on branch qti-conformance-coverage, gates green. F (rubric) is the only remaining test-export-adjacent gap: the conform-ed test view does not yet carry rubric blocks, so authoring + emitting them needs a view+inverse extension (same release cadence as any engine gap).

  • The §5 item-authoring pattern (itemDraft union + buildAuthoredItemDocument + contract guard), QtiItemAuthorPanel, and the ADR-0020 ConditionBuilder / outcome vocabulary.
  • conform-ed serializers + contracts for every construct (the engine is complete).
  • The test:qti:conformance lane (extend per slice) + the vendored-fixtures convention.
  • The Content-Package builder (buildQtiItemContentPackage) — extend for stimulus resources (E).
  • typesafe-i18n workflow; Mantine theme from packages/ui.
  • Per slice: bun test (touched pkg) + bun run typecheck; after UI slices bun run validate:full (incl. i18n guard + component tests + 100% domain coverage).
  • Conformance: each slice adds its emitted artifact to test:qti:conformance and, where a corpus example exists, promotes it from the :local backlog into the deterministic set.
  • Slices touching the DB (D profile, E stimulus bank) also run bun run test:integration; the agent regenerates the migration set per the runbook and the container gates apply it (see “Migrations & DB” — no dev-DB dependency).
  • O-1 (PNP locus) — RESOLVED: learner-owned, person-scoped accessibility profile (teacher/admin proxy allowed); see slice D.
  • O-2 (stimulus storage) — RESOLVED: a first-class stimulus bank; see slice E.
  • O-3 (test export) — RESOLVED + DONE: the conform-ed assessmentTestDocumentFromView inverse shipped in 0.0.23 (pinned); test export + the self-contained test package + their conformance gates landed 2026-06-16 (branch qti-conformance-coverage). Only F’s emitted-test rubric gate remains (needs the conform-ed test view to carry rubric blocks). Nothing else is blocked on Anton.