Canonical format, version 1. The resolver and evaluation shapes below match
src/core/course/resolve-binding.ts and the exercise types.evaluation.
Resolving bindings
Build a resolver from the loaded course (a map of records and assets), then resolve any binding to aResolvedValue. Resolution never throws: an unresolved reference returns
{ kind: "missing", reason } so a broken reference degrades instead of crashing.
Rendering fragments
ARenderFragment pairs a binding with a role (primary, supporting-text, visual,
audio, translation, and so on). Resolve the binding, then render by role and value kind:
text values as text, asset values by asset kind (image, audio player, video), and a
record value with its presentation. Roles are open strings; render the ones you know and
fall back sensibly for the rest.
Grading
Every exercise carries oneevaluation. Grade against stable IDs or accepted-value
bindings, never against displayed text.
Accepted values and normalization
Typed grading resolvesaccepted bindings (usually a field such as
field_alternate_answers) and compares under normalization, so “a cat” and “cats” pass
without duplicating text in the exercise.
Localized authored text
Titles, instructions, and literal text fragments may be a plain string or a map of locale tag to string. Resolve against the course’sdefaultLocale, or against the learner’s
language if you offer one: try an exact tag, then the base language (pt-BR to pt), then
any available entry.
locale.
Media playback
Anasset resolution gives you the Asset record. Load the binary from the asset’s own
directory using its file (when availability is ready); a placeholder asset has no
file yet. Use mimeType to choose the player.