- In progress (remaining question-type work; exercise question sections and video recording are tracked as separate shipped PRDs — see PRD-TRACKER DONE)
- See [implementation-plan.md](./implementation-plan.md) for ticket breakdown and delivery sequencing.
## Purpose
Expand ClassroomIO exercise questions beyond `single answer`, `multiple answers`, and `paragraph`, so instructors can run stronger assessments, reduce manual grading where possible, and collect richer assignment submissions inside the LMS.
## Problem Statement
Current exercise functionality is constrained by three legacy question types and a grading/answer model tuned for those types. This creates four product issues:
1. Limited assessment design for instructors.
2. Lower auto-grading coverage.
3. Weak first-class support for assignment-style submissions.
4. Increased instructor grading overhead and external-tool leakage.
## Current-State Audit
| Area | Current State | Gaps |
| --- | --- | --- |
| Question types | `RADIO`, `CHECKBOX`, `TEXTAREA` only | No true/false, numeric, fill-blank, matching, ordering, file-upload, hotspot |
| DB `question_type` | Seeded from `packages/db/src/utils/seed/questionType.ts` | Typename coverage too narrow |
| Validation constants | `QUESTION_TYPE` in `packages/utils/src/validation/constants.ts` contains only 3 numeric IDs | Hardcoded numeric assumptions are fragile as type set grows |
| Exercise validation | `packages/utils/src/validation/exercise/exercise.ts` has option rules for radio/checkbox + textarea | No schema-per-type authoring or submission validation |
| Exercise authoring UI | `edit-mode.svelte` renders only radio, checkbox, textarea | No renderer registry or extensibility contract |
| Exercise taking UI | `view-mode.svelte` answer flow assumes options or open text | No type-specific interaction patterns for new formats |
| Submission model | `question_answer` stores `answers[]` + `open_answer` | No structured payload for richer responses (fill blanks, ordering, matching, uploads) |
| Attempt controls | No max-attempt rule or attempt scoring strategy on `exercise` | Cannot configure highest/latest/average grading behavior |
| Test controls | No persisted timer/randomization/availability settings on exercise | Missing in-schema support for test-mode controls |
| File response support | No exercise-question-level upload config | Cannot do per-question file constraints |
- Students answering exercises on desktop and mobile.
- Admins and tutors grading and reviewing progress.
## Goals
1. Support additional objective and subjective question types.
2. Increase auto-grading coverage for objective formats.
3. Add first-class assignment upload support at question level.
4. Keep authoring UX consistent across question types.
5. Add explicit exercise-level controls for attempts, scoring rule, answer reveal, and test behavior.
## Non-Goals (v1)
- Online proctoring.
- AI-generated grading feedback.
- Code execution/judging sandboxes.
- LTI/QTI export.
- Negative marking.
- Audio/video response question type.
## Confirmed Decisions
1. Code execution is out of scope.
2. Upload size limits are plan-based: Free `2MB`, Paid `10MB`.
3. Resubmission policy is exercise-level, not per question.
4. Rollout phases remain `P0`, `P1`, `P2`.
5. If an exercise contains `short answer` or `paragraph`, final grading is manual.
6. Numeric-answer grading mode is configurable.
7. Fill-in-the-blank does not support multiple accepted answers per blank in v1.
8. Partial credit is enabled by default where supported.
9. Partial credit settings are question-level with exercise-level override.
10. File upload configuration is per question.
11. Exercise settings include max attempts.
12. Correct-answer visibility is exercise-level configurable.
13. Test-only controls are in scope.
14. Allowed upload file types in v1: `PDF`, `DOCX`, `PPTX`, `XLSX`, `ZIP`, and images.
15. Attempt grading rule is exercise-level configurable: `highest`, `latest`, `average`.
16. Upload question accepts exactly one file in v1.
## Proposed Question Types
| Type | Auto-gradable | Partial Credit | Assignment Fit | Test Fit | Phase |
| --- | --- | --- | --- | --- | --- |
| True/False | Yes | No | Medium | High | P0 |
| Short Answer (single-line) | No | N/A | High | High | P0 |
| Numeric Answer | Yes | Optional | Medium | High | P0 |
| Fill in the Blank | Yes | Yes | Medium | High | P0 |
| File Upload | No | N/A | High | Low | P0 |
| Matching | Yes | Yes | Medium | High | P1 |
| Ordering/Sequence | Yes | Yes | Medium | High | P1 |
| Hotspot/Image Labeling | Yes | Optional | Medium | Medium | P2 |
## Functional Requirements
### Authoring
- Instructor can choose question type from a type picker.
- Instructor can configure:
- prompt
- points
- required/optional
- per-question instructions
- type-specific settings
- Instructor can define answer key for auto-graded types.
- Instructor can configure scoring mode (`all_or_nothing` or `partial`) where supported.
- Instructor can preview question behavior before publish.
### Student Experience
- Students can answer all released types on desktop and mobile.
- Answers autosave while taking exercise.
- One exercise can contain mixed question types.
- File upload question enforces allowed MIME/extensions and plan-based limits.
- File upload question accepts one file in v1.
### Grading
- Objective types auto-grade immediately unless exercise is in manual-only mode.
- Manual types route to grading queue with teacher feedback.
- Instructors can override auto-graded scores.
- Gradebook stores per-question points and final exercise score.
- Exercise-level `auto-grade` toggle can only be enabled when all active question types are auto-gradable; otherwise it must be disabled with a hint message.
- renderer registry/contracts live in `@cio/question-types`.
- answer serialization and shared form-state utilities live in `@cio/question-types`.
- render contract object lives in `@cio/question-types` (`ExerciseQuestionRenderContract` / `ExerciseQuestionListRenderContract`) and is deterministic for the same inputs.
- question type renderer components live in `@cio/ui/custom/exercise-question`.
-`@cio/ui/custom/exercise-question` is components-only and does not own shared exercise logic.
- dashboard screens consume type keys/contracts from `@cio/question-types` and renderers from `@cio/ui/custom/exercise-question`.
### 1.2 Cross-App File Contract
- The complete individual file list for reusable shared packages is defined in `implementation-plan.md` under `Shared Package File Contract (Cross-App Reuse)`.
- Shared package code must stay app-agnostic so any app can consume it to build an exercise/forms product.